/* AUTO-GENERERAD av scripts/build-design-floor.js — redigera INTE.
   Kalla: functions/api/v1/project/_lib/design-floor.js
   Gate 4n avvisar bygget om filen inte ar identisk med modulen. */
/* Farg-tokens registrerade som <color> sa de INTERPOLERAR vid morph (color-mix-harledda farger hoppar annars). */ @property --primary{syntax:'<color>';inherits:true;initial-value:transparent} @property --primary-readable{syntax:'<color>';inherits:true;initial-value:transparent} @property --accent-readable{syntax:'<color>';inherits:true;initial-value:transparent} @property --secondary{syntax:'<color>';inherits:true;initial-value:transparent} @property --accent{syntax:'<color>';inherits:true;initial-value:transparent} @property --surface-base{syntax:'<color>';inherits:true;initial-value:transparent} @property --background{syntax:'<color>';inherits:true;initial-value:transparent} @property --surface{syntax:'<color>';inherits:true;initial-value:transparent} @property --text{syntax:'<color>';inherits:true;initial-value:transparent} @property --muted{syntax:'<color>';inherits:true;initial-value:transparent} @property --border{syntax:'<color>';inherits:true;initial-value:transparent} @property --chrome-bg{syntax:'<color>';inherits:true;initial-value:transparent} @property --card-bg{syntax:'<color>';inherits:true;initial-value:transparent} @property --nav-active-bg{syntax:'<color>';inherits:true;initial-value:transparent} @property --on-accent-surface{syntax:'<color>';inherits:true;initial-value:transparent} @property --on-primary{syntax:'<color>';inherits:true;initial-value:transparent} @property --on-secondary{syntax:'<color>';inherits:true;initial-value:transparent} @property --on-success{syntax:'<color>';inherits:true;initial-value:transparent} @property --on-warning{syntax:'<color>';inherits:true;initial-value:transparent} @property --on-danger{syntax:'<color>';inherits:true;initial-value:transparent} @property --on-info{syntax:'<color>';inherits:true;initial-value:transparent} @property --badge-text{syntax:'<color>';inherits:true;initial-value:transparent} @property --sidebar-bg{syntax:'<color>';inherits:true;initial-value:transparent} @property --sidebar-text{syntax:'<color>';inherits:true;initial-value:transparent} @property --success{syntax:'<color>';inherits:true;initial-value:transparent} @property --warning{syntax:'<color>';inherits:true;initial-value:transparent} @property --danger{syntax:'<color>';inherits:true;initial-value:transparent} @property --info{syntax:'<color>';inherits:true;initial-value:transparent} @property --success-text{syntax:'<color>';inherits:true;initial-value:transparent} @property --warning-text{syntax:'<color>';inherits:true;initial-value:transparent} @property --danger-text{syntax:'<color>';inherits:true;initial-value:transparent} @property --info-text{syntax:'<color>';inherits:true;initial-value:transparent} @property --success-bg{syntax:'<color>';inherits:true;initial-value:transparent} @property --warning-bg{syntax:'<color>';inherits:true;initial-value:transparent} @property --danger-bg{syntax:'<color>';inherits:true;initial-value:transparent} @property --info-bg{syntax:'<color>';inherits:true;initial-value:transparent} @property --badge-bg{syntax:'<color>';inherits:true;initial-value:transparent} @property --w-shadow{syntax:'<number>';inherits:false;initial-value:1}

@layer eontra.reset, eontra.base, eontra.layout, eontra.components, eontra.state, eontra.utility;

@layer eontra.reset {
  *, *::before, *::after { box-sizing: border-box; }
  /* HORN-FORM: corner_style styr CSS corner-shape pa rektangulara ytor och kontroller. Ingen effekt utan radie; degraderar till round i browsers utan stod. Cirklar (avatar/dot, radius-full) lamnas ororda med flit. */
  :where(.card, .panel, .surface, button, .btn, input, textarea, select, fieldset, details, dialog, .alert, .badge, .tag, .chip, .nav-item, pre, kbd) { corner-shape: var(--corner-shape, round); }
  * { margin: 0; }
  html { -webkit-text-size-adjust: 100%; tab-size: 4; scroll-behavior: smooth; }
  body { min-height: 100svh; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; }
  img, svg, video, canvas, audio, iframe, embed, object { display: block; max-width: 100%; }
  img, video { height: auto; }
  input, button, textarea, select { font: inherit; color: inherit; }
  p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
  ul[role="list"], ol[role="list"] { list-style: none; padding: 0; } :where(nav, header, aside, .nav, .navbar, .rail, .tabs, .menu, .toolbar, .sidebar, .header, .app-header, .topbar, [role=navigation], [role=banner], [role=menubar], [role=tablist]) :where(ul, ol), :where(ul, ol):where([class*=nav], [class*=menu], [class*=sidebar], [class*=toolbar], [class*=breadcrumb]) { list-style: none; padding: 0; margin: 0; }
  :where(a):not([class]) { color: var(--primary-readable, var(--primary)); text-underline-offset: 0.18em; }
}

@layer eontra.base {
  /* KOMPAT-ALIAS: vanliga token-namn fran andra designsystem (Tailwind/shadcn) som modellen ibland skriver i stallet for golvets. Bara ENTYDIGA universella namn, resolvade till golv-tokenet sa app-CSS som anvander dem inte tyst gor ingenting. I eontra.base → en app som definierar egna vinner. Tvetydiga/numrerade skalor (--scale-N m.fl.) aliasas EJ; render-rapporten flaggar dem i stallet. */
  :root { --canvas: var(--background); --text-muted: var(--muted); --surface-hover: var(--accent-surface, color-mix(in srgb, var(--text) 6%, transparent)); --shadow-xl: var(--shadow-modal); --font-size-lg: var(--font-size-large); --font-size-sm: var(--font-size-small); }
  body {
    /* Ingen egen bakgrund pa body med flit: html bar var(--background) i bas-lagret, och en opak body hade malat over atmosfar-lagret (bakgrundselementet ligger pa negativ z-index, bakom body) sa atmosphere/grain/pattern/vignette slocknade tyst. Canvasen kommer fran html. */
    color: var(--text);
    font-family: var(--font-family);
    font-size: var(--font-size-body, var(--font-size, 1rem));
    font-weight: var(--font-weight-body, 400);
    line-height: var(--line-height-body, 1.6); font-optical-sizing: auto; font-kerning: normal; font-variant-ligatures: common-ligatures contextual;
  }
  :where(h1, h2, h3, h4, h5, h6) {
    margin-block: 0 var(--space-sm);
    font-family: var(--font-heading, var(--font-family));
    font-weight: calc(var(--font-weight-heading, 700) * var(--w-text, 1));
    line-height: var(--line-height-tight, 1.15);
    letter-spacing: var(--letter-spacing-heading, -0.02em); text-box: trim-both cap alphabetic;
    text-wrap: balance;
  }
  :where(h1) { font-size: var(--font-size-h1, clamp(1.75rem, 1.2rem + 2.4vw, 2.6rem)); }
  :where(h2) { font-size: var(--font-size-h2, clamp(1.35rem, 1.1rem + 1.2vw, 1.85rem)); }
  :where(h3) { font-size: var(--font-size-h3, 1.2rem); }
  :where(h4, h5, h6) { font-size: var(--font-size-label, 0.95rem); }
  :where(p, ul, ol, dl, blockquote, figure, pre, table) { margin-block: 0 var(--space-md); }
  :where(p, li) { text-wrap: pretty; }
  :where(* + h1, * + h2, * + h3, * + h4, * + h5, * + h6) { margin-block-start: var(--space-lg); }
  :where(ul, ol):not([role="list"]):not(:where(nav, header, aside, .nav, .navbar, .rail, .tabs, .menu, .toolbar, .sidebar, .header, .app-header, .topbar, [role=navigation], [role=banner], [role=menubar], [role=tablist]) *):not(:where([class*=nav], [class*=menu], [class*=sidebar], [class*=toolbar], [class*=breadcrumb])) { padding-inline-start: var(--space-lg); }
  :where(li + li):not(:where([role="list"], nav, .nav, .rail, .tabs) *) { margin-block-start: var(--space-xs); }
  :where(a) { color: var(--primary-readable, var(--primary)); text-decoration-thickness: 1px; transition: color calc(var(--transition-fast, .15s) * var(--motion-scale, 1)) var(--ease-standard, ease); }
  :where(a:hover) { color: var(--accent-readable, var(--accent, var(--primary))); }
  :where(strong, b) { font-weight: 700; }
  :where(small) { font-size: var(--font-size-small, .85em); color: var(--muted); }
  :where(hr) { border: 0; border-block-start: var(--border-width, 1px) var(--border-style, solid) var(--border); margin-block: var(--space-lg); }
  :where(blockquote) {
    padding-inline-start: var(--space-md);
    border-inline-start: 3px solid var(--primary);
    color: var(--muted); font-style: italic;
  }
  :where(code, kbd, samp) { font-family: var(--font-mono, ui-monospace, monospace); font-size: .9em; }
  :where(:not(pre) > code) {
    background: var(--accent-surface, color-mix(in srgb, var(--primary) 8%, transparent));
    color: var(--on-accent-surface, var(--primary));
    padding: .15em .4em; border-radius: calc((var(--radius-sm, .25rem)) * var(--radius-scale, 1));
  }
  :where(pre) {
    background: var(--surface); color: var(--text);
    border: var(--border-width, 1px) var(--border-style, solid) var(--border);
    border-radius: calc((var(--radius, .5rem)) * var(--radius-scale, 1));
    padding: var(--space-md); overflow-x: auto; line-height: 1.5;
  }
  :where(kbd) {
    background: var(--surface); border: 1px solid var(--border);
    border-block-end-width: 2px; border-radius: calc((var(--radius-sm, .25rem)) * var(--radius-scale, 1));
    padding: .1em .4em; font-size: .85em;
  }
  :where(table) { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
  :where(th, td) { padding: var(--space-sm) var(--space-md); text-align: start; border-block-end: 1px solid var(--border); }
  :where(thead th) { position: sticky; inset-block-start: 0; z-index: 1; background: var(--table-header-bg, var(--surface)); font-size: var(--font-size-label, .85rem); font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
  :where(tbody tr:last-child td) { border-block-end: 0; } :where(tbody tr):hover { background: var(--table-hover, color-mix(in srgb, var(--primary) 4%, transparent)); color: var(--divider-alt-text, var(--text)); } :where(th[aria-sort]) { cursor: pointer; user-select: none; } :where(th[aria-sort="ascending"])::after { content: "↑"; opacity: .7; } :where(th[aria-sort="descending"])::after { content: "↓"; opacity: .7; } :where(th[aria-sort="none"])::after { content: "↕"; opacity: .35; }
  :where(caption, figcaption) { color: var(--muted); font-size: var(--font-size-small, .85rem); }
  :where(mark) { background: var(--warning-bg, color-mix(in srgb, var(--warning, gold) 30%, transparent)); color: var(--warning-text, var(--text)); padding: 0 .2em; }
  :where(label):not(:has(input[type="checkbox"], input[type="radio"])) { display: block; font-size: var(--font-size-label, .9rem); font-weight: 600; margin-block-end: var(--space-xs); }
  :where(input, textarea, select) {
    inline-size: auto; max-inline-size: 100%; padding: var(--space-sm) var(--space-md);
    background: var(--background); color: var(--text);
    border: var(--border-width, 1px) var(--border-style, solid) var(--border);
    border-radius: calc((var(--radius, .5rem)) * var(--radius-scale, 1));
    transition: border-color calc(var(--transition-fast, .15s) * var(--motion-scale, 1)), box-shadow calc(var(--transition-fast, .15s) * var(--motion-scale, 1));
  }
  :where(input, textarea, select):hover { border-color: color-mix(in srgb, var(--primary) 35%, var(--border)); }
  :where(input, textarea, select):focus-visible { outline: 0; border-color: var(--primary-readable, var(--primary)); box-shadow: var(--shadow-focus, 0 0 0 3px color-mix(in srgb, var(--primary-readable, var(--primary)) 35%, transparent)); }
  :where(input[type="checkbox"], input[type="radio"]) { inline-size: auto; accent-color: var(--primary); }
  :where(textarea) { min-block-size: 6rem; resize: vertical; }
  :where(fieldset) { border: 1px solid var(--border); border-radius: calc((var(--radius, .5rem)) * var(--radius-scale, 1)); padding: var(--space-md); }
  :where(legend) { padding-inline: var(--space-xs); font-weight: 600; }
  /* VALIDERINGSTILLSTAND: golvet saknade helt fel-styling. Nu bar det danger-kant + laskontrast-text
     (--danger/--danger-text fran kontrast-passet, WCAG-garanterade). aria-invalid="true" ar APP-STYRD
     (fyras aldrig for tidigt); :user-invalid tacker inbyggd validering, fyras FORST efter interaktion
     (undviker rodfarg-vid-sidladdning). .field-error = felmeddelande, .hint = hjalptext. */
  :where(input, textarea, select)[aria-invalid="true"],
  :where(input, textarea, select):user-invalid { border-color: var(--danger, crimson); }
  :where(input, textarea, select)[aria-invalid="true"]:focus-visible,
  :where(input, textarea, select):user-invalid:focus-visible {
    border-color: var(--danger, crimson);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger, crimson) 30%, transparent);
  }
  :where(input, textarea, select)[aria-invalid="false"] { border-color: var(--success, green); }
  :where(.field-error, .error-text) {
    display: block; margin-block-start: var(--space-2xs, .25rem);
    color: var(--danger-text, var(--danger, crimson));
    font-size: var(--font-size-small, .85rem); font-weight: 500;
  }
  :where(.hint, .form-hint) {
    display: block; margin-block-start: var(--space-2xs, .25rem);
    color: var(--muted); font-size: var(--font-size-small, .85rem);
  }
  /* Glod och Rorelse hade doda tokens: --shadow-glow och --transition-base
       harleddes men lastes av ingen regel. Nu bar knapparna dem. */
    :where(button, .btn):hover:not(:disabled) { box-shadow: var(--shadow-glow, none); }
    .btn[data-variant="secondary"] { background: var(--secondary); color: var(--on-secondary, var(--on-primary)); border-color: transparent; }
    .badge[data-variant="secondary"], .tag[data-variant="secondary"] { background: var(--secondary); color: var(--on-secondary, var(--on-primary)); }
    .btn[data-variant="primary"], .btn-primary { background: var(--gradient-primary, var(--primary)); color: var(--on-gradient, var(--on-primary)); border-color: transparent; }
    :where(button, .btn, [type="button"], [type="submit"], [type="reset"]) {
    transition: background calc(var(--transition-base, .2s) * var(--motion-scale, 1)) ease, box-shadow calc(var(--transition-base, .2s) * var(--motion-scale, 1)) ease, border-color calc(var(--transition-base, .2s) * var(--motion-scale, 1)) ease;
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-xs);
    padding: var(--space-sm) var(--space-lg);
    background: var(--primary); color: var(--on-primary, #fff);
    border: var(--border-width, 1px) var(--border-style, solid) transparent;
    border-radius: calc((calc(var(--radius, .5rem) * var(--w-radius, 1))) * var(--radius-scale, 1));
    font-weight: 600; line-height: 1.2; cursor: pointer; text-decoration: none; box-shadow: var(--elevation-edge, 0 0 transparent);
    transition: transform calc(var(--transition-fast, .15s) * var(--motion-scale, 1)) var(--ease-standard, ease),
                box-shadow calc(var(--transition-fast, .15s) * var(--motion-scale, 1)), background calc(var(--transition-fast, .15s) * var(--motion-scale, 1)), opacity calc(var(--transition-fast, .15s) * var(--motion-scale, 1));
  }
  :where(button, .btn):hover { transform: translateY(calc(var(--hover-lift, 1px) * var(--w-motion, 1) * -1)); box-shadow: var(--shadow-raised, 0 2px 8px rgb(0 0 0 / .12)); }
  :where(button, .btn):active { transform: none; }
  :where(button, .btn):disabled, :where(button, .btn)[aria-disabled="true"] { opacity: .55; cursor: not-allowed; transform: none; box-shadow: none; }
  :where(details) { border: 1px solid var(--border); border-radius: calc((var(--radius, .5rem)) * var(--radius-scale, 1)); padding: var(--space-sm) var(--space-md); }
  :where(summary) { cursor: pointer; font-weight: 600; }
  :where(dialog) {
    border: 1px solid var(--border); border-radius: var(--modal-radius, calc((var(--radius-lg, .75rem)) * var(--radius-scale, 1)));
    background: var(--modal-bg, var(--surface)); color: var(--modal-text, var(--text));
    padding: var(--modal-pad, var(--space-lg)); box-shadow: var(--modal-shadow, var(--shadow-modal, 0 20px 60px rgb(0 0 0 / .25))); min-inline-size: min(18rem, 90vw); max-inline-size: var(--modal-max, min(40rem, 92vw));
  }
  /* MODAL SOTA: storleks-varianter (open-mekanik data-modal-open/close finns redan; native <dialog> ger focus-trap+escape) */
  :where(dialog)[data-size="sm"] { --modal-max: min(24rem, 92vw); }
  :where(dialog)[data-size="lg"] { --modal-max: min(56rem, 94vw); }
  :where(dialog)[data-size="full"] { --modal-max: 100vw; --modal-radius: 0; inline-size: 100vw; block-size: 100dvh; }
  :where(dialog)::backdrop { background: rgb(0 0 0 / .45); backdrop-filter: blur(2px); }
  :where(progress) { inline-size: 100%; block-size: .5rem; accent-color: var(--primary); }
  :where(::selection) { background: color-mix(in srgb, var(--primary) 25%, transparent); }
  :where(::placeholder) { color: var(--muted); opacity: 1; }
}


@layer eontra.layout {
  /* ── App shell: hela kompositionen deklareras med tva custom properties ──
     <div class="app-shell" style="--areas:'h h h' 'l m r' 'f f f'; --cols:240px 1fr 280px">
       <header data-region="h">  <aside data-region="l">  <main data-region="m"> ...
     Regionnamnen ar fria: [data-region] mappas automatiskt till grid-area.        */
  .app-shell {
    display: grid;
    grid-template-areas: var(--areas, "header" "main" "footer");
    grid-template-columns: var(--cols, 1fr);
    grid-template-rows: var(--rows, auto 1fr auto);
    min-block-size: 100svh;
    gap: var(--shell-gap, 0);
  }
  .app-shell > [data-region] { grid-area: var(--region, auto); min-inline-size: 0; }
  /* IDENTITETSMAPPNING: grid-area-namnet ar EXAKT det attributet sager.
     Tidigare mappades korta namn till langa (h -> header), vilket gjorde att
     --areas:"h h h" deklarerade omraden som inget element nagonsin placerades i.
     Allt auto-placerades och layouten kollapsade. Nu maste namnet i --areas vara
     samma strang som i data-region — sjalvkonsistent och omojligt att kombinera fel. */
  [data-region="header"] { --region: header; } [data-region="h"] { --region: h; }
  [data-region="main"]   { --region: main; }   [data-region="m"] { --region: m; }
  [data-region="footer"] { --region: footer; } [data-region="f"] { --region: f; }
  [data-region="left"]   { --region: left; }   [data-region="l"] { --region: l; }
  [data-region="right"]  { --region: right; }  [data-region="r"] { --region: r; }
  [data-region="aside"]  { --region: aside; }  [data-region="nav"] { --region: nav; }
  [data-region="a"] { --region: a; } [data-region="b"] { --region: b; }
  [data-region="c"] { --region: c; } [data-region="d"] { --region: d; }

  /* LAYOUT-PRESETS: namngivna app-shell-kompositioner. data-layout satter --areas/--cols/--rows sa AI:n slipper hand-komponera rutnatet — mekaniskt, och byggets vanligaste fel (kolumner vs spar). Inline style="--areas:..." VINNER over presetten (hogre specificitet) sa ett bespoke skal kan alltid overrida. Mobil: golvets auto-stack (<40rem, en kolumn i DOM-ordning) galler som vanligt; lagg data-collapse/data-drawer for sidopanels-kollaps/drawer. Regionnamnen ar de KORTA (h/l/m/r/f) — matcha med data-region pa varje region. Valj presetten vars region-set matchar din design. --rail-l/--rail-r tunar sidopanels-bredderna utan att rora --areas. */
  .app-shell[data-layout="holy-grail"]  { --areas: "h h h" "l m r" "f f f"; --cols: var(--rail-l, 15rem) 1fr var(--rail-r, 17rem); --rows: auto 1fr auto; }
  .app-shell[data-layout="sidebar"]      { --areas: "h h" "l m" "f f"; --cols: var(--rail-l, 15rem) 1fr; --rows: auto 1fr auto; }
  .app-shell[data-layout="sidebar-full"] { --areas: "l h" "l m" "l f"; --cols: var(--rail-l, 15rem) 1fr; --rows: auto 1fr auto; }
  .app-shell[data-layout="content-rail"] { --areas: "h h" "m r" "f f"; --cols: 1fr var(--rail-r, 17rem); --rows: auto 1fr auto; }
  .app-shell[data-layout="topbar"]       { --areas: "h" "m" "f"; --cols: 1fr; --rows: auto 1fr auto; }

  /* ── Layoutprimitiver: mekanik, inte utseende ───────────────────────── */
  .stack { display: flex; flex-direction: column; gap: calc(var(--gap, var(--space-md)) * var(--w-space, 1)); }
  .stack > * { margin-block: 0; }
  .cluster { display: flex; flex-wrap: wrap; align-items: var(--align, center); gap: var(--gap, var(--space-sm)); }
  .cluster[data-justify="between"] { justify-content: space-between; }
  .cluster[data-justify="end"] { justify-content: flex-end; }
  .cluster[data-justify="center"] { justify-content: center; }
  .grid { display: grid; gap: calc(var(--gap, var(--space-md)) * var(--w-space, 1)); grid-template-columns: repeat(auto-fit, minmax(var(--min, 16rem), 1fr)); } /* GRID-DEFAULT = auto-FIT: fa objekt (t.ex. 3 feature-kort) FYLLER raden i stallet for att vansterklumpas. auto-fill lamnade tomma fantom-kolumner till hoger nar objekt < kolumner (uppmatt: 3 kort i ~1200px gav 5 spar, 3 fyllda vanster + 2 tomma hoger). auto-fit kollapsar de tomma sparen sa korten stracks ut jamnt. Fullfyllda grid opaverkas (auto-fit == auto-fill nar raden fylls); bara sista ofullstandiga raden + fa-objekt-fallet andras. Vaxande samlingar dar kort ska BEHALLA bredd (produktlistor) opt-in:ar auto-fill med data-fill. */ .grid[data-fill] { grid-template-columns: repeat(auto-fill, minmax(var(--min, 16rem), 1fr)); }
  .grid[data-fit] { grid-template-columns: repeat(auto-fit, minmax(var(--min, 16rem), 1fr)); }
  .switcher { display: flex; flex-wrap: wrap; gap: var(--gap, var(--space-md)); }
  .switcher > * { flex-grow: 1; flex-basis: calc((var(--threshold, 30rem) - 100%) * 999); }
  .sidebar-layout { display: flex; flex-wrap: wrap; gap: var(--gap, var(--space-lg)); }
  .sidebar-layout > :first-child { flex-basis: var(--side, var(--aside-width, 16rem)); flex-grow: 1; }
  .sidebar-layout > :last-child { flex-basis: 0; flex-grow: 999; min-inline-size: var(--content-min, var(--pane-min, 50%)); }
  /* KOLLAPS-FALLA, uppmatt i drift: `.center` hade BARA max-inline-size och lat
     inline-size vara auto. Pa ett rutnats-barn med auto-marginaler i inline-axeln
     galler inte stretch — objektet far sin fit-content-storlek i stallet. Och
     eftersom regionerna bar `container-type: inline-size` (raden langst ner i det
     har lagret) ar deras inre storlekar noll per containment-reglerna. fit-content
     av noll ar noll: `<main data-region="m" class="center">` kollapsade till en
     teckenbred spalt, rubriken bots ett tecken per rad av reset-lagrets
     overflow-wrap. Kombinationen ar dessutom EXAKT den builder.md dokumenterar.
     Losningen ar en BESTAMD inline-storlek: da galler varken stretch-regeln eller
     fit-content, och auto-marginalerna gor bara det de ska — centrerar. */
  .center { box-sizing: content-box; margin-inline: auto; inline-size: min(100%, var(--measure, 68ch)); max-inline-size: var(--measure, 68ch); }
  .center[data-text] { text-align: center; }
  .cover { display: flex; flex-direction: column; min-block-size: var(--min-h, 100svh); }
  .cover > .cover-center { margin-block: auto; }
  .frame { aspect-ratio: var(--ratio, 16 / 9); overflow: hidden; }
  .frame > * { inline-size: 100%; block-size: 100%; object-fit: var(--fit, cover); }
  /* TEXT-OVER-BILD (scrim): text pa en fotografisk bakgrund byter laslighet beroende pa vilka pixlar
     den hamnar over — uppmatt foll en rubrik till 1.0-1.9 over morka partier och 5.2 over ljusa i SAMMA
     hero. Golvet garanterar kontrast mot YTOR men kunde inget om foton. En scrim (halvgenomskinlig tint
     mellan bild och text) plattar bakgrunden till en forutsagbar ton sa texten far ett kontrast-GOLV
     oavsett fotots innehall. Uppmatt: 0.55 mork scrim ger vit text 5.1 mot fotots ljusaste punkt.
     AUTO pa sektioner med inline bakgrundsbild (sa modellens vanliga hero-markup skyddas utan att den
     minns nagot); .overlay for bild satt via stilark. Tunbar: --overlay-strength (0 = av, for en hero
     som redan ar mork nog), --overlay-tint (mork default; satt till en ljus ton for mork text pa ljust
     foto), --overlay-dir (cover = jamn tint, bottom/top = gradient nar texten bara ligger i ena anden). */
  .overlay, section[style*="url("] {
    position: relative; isolation: isolate;
  }
  .overlay::after, section[style*="url("]::after {
    content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background: var(--overlay-dir-value,
      color-mix(in srgb, var(--overlay-tint, #000) calc(var(--overlay-strength, .55) * 100%), transparent));
  }
  .overlay > *, section[style*="url("] > * {
    position: relative; z-index: 1;
  }
  /* Text i en scrimmad yta blir ljus och laskontrast-behandlad (samma readable-familj som resten). */
  .overlay:where(:not([data-overlay-text="dark"])), section[style*="url("]:where(:not([data-overlay-text="dark"])) {
    --text: var(--overlay-text-color, #fff); --muted: color-mix(in srgb, #fff 78%, transparent);
    color: var(--overlay-text-color, #fff);
  }
  .reel { display: flex; gap: var(--gap, var(--space-md)); overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: thin; }
  .reel > * { scroll-snap-align: start; flex: 0 0 var(--item, 18rem); } /* MARQUEE/TICKER: kontinuerlig horisontell rullning (status-band, nyhets-ticker). Somlos loop kraver dubblerat innehall — Eontra.marquee (SDK) bygger sparet och klonar innehallet automatiskt sa man skriver items EN gang. WCAG 2.2.2: stannar HELT under prefers-reduced-motion OCH pausar pa hover/fokus; SDK injicerar dessutom en paus-knapp (opt-out data-no-pause). --marquee-speed (varaktighet, default 25s), --marquee-direction (normal=vanster, reverse=hoger). */ .marquee { position: relative; overflow: hidden; } .marquee-track { display: flex; inline-size: max-content; gap: var(--marquee-gap, var(--space-xl, 2rem)); align-items: center; animation: eontra-marquee var(--marquee-speed, 25s) linear infinite; animation-direction: var(--marquee-direction, normal); will-change: transform; } .marquee:hover .marquee-track, .marquee:focus-within .marquee-track, .marquee[data-paused] .marquee-track { animation-play-state: paused; } .marquee-pause { position: absolute; inset-block-start: var(--space-xs, .25rem); inset-inline-end: var(--space-xs, .25rem); z-index: 2; inline-size: var(--tap-min, 2rem); block-size: var(--tap-min, 2rem); padding: 0; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-full, 999px); border: 1px solid var(--border); background: color-mix(in srgb, var(--surface) 82%, transparent); color: var(--text); cursor: pointer; opacity: .65; } .marquee-pause:hover, .marquee-pause:focus-visible { opacity: 1; } .marquee[data-no-pause] .marquee-pause { display: none; } /* SCOPED TEXTUR (dekorativ, kontrast-vaktad): data-texture=grid|dots|lines lagger en NEUTRAL geometrisk textur bakom EN ytas innehall (ej global som pattern/grain-koordinaterna). Lag opacitet default sa text forblir laslig; --texture-strength (0-1), --texture-color (default text-ton, adapterar mot tema), --texture-size. Bakom innehall (::before z 0 + barn z 1, samma stacking som scrim). Statisk → ingen reduced-motion-fraga. */ [data-texture] { position: relative; isolation: isolate; } [data-texture] > * { position: relative; z-index: 1; } [data-texture]::before { content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none; color: var(--texture-color, var(--text)); background-repeat: repeat; background-size: var(--texture-size, 24px 24px); } [data-texture=grid]::before { background-image: linear-gradient(to right, currentColor 1px, transparent 1px), linear-gradient(to bottom, currentColor 1px, transparent 1px); opacity: var(--texture-strength, .05); } [data-texture=dots]::before { background-image: radial-gradient(currentColor 1px, transparent 1.6px); opacity: var(--texture-strength, .08); } [data-texture=lines]::before { background-image: repeating-linear-gradient(45deg, currentColor 0 1px, transparent 1px var(--texture-line-gap, 10px)); background-size: auto; opacity: var(--texture-strength, .05); }
  .pad { padding: var(--pad, var(--space-lg)); }
  .pad-x { padding-inline: var(--pad, var(--space-lg)); }
  .pad-y { padding-block: var(--pad, var(--space-lg)); }
  /* SEKTIONS-RYTM: golvet gav <section> VARKEN padding eller margin, sa nakna sidnivasektioner
     jammade ihop — innehallet klistrades mot kanten och fargade band nuddade nasta sektion utan luft
     (uppmatt i drift: stats-band + meny-sektion, bada med 0 topp-inset). Fixen ar PADDING, inte margin:
     ett band SKA nudda nasta band (margin hade punsat gap och visat body-bakgrund emellan) — det ar
     innehallet inuti varje sektion som behover andas. Skopat till main > section (sidniva, ej nastlade)
     och :where() sa .pad-y/.stack eller --section-space:0 alltid vinner. En full-bleed hero nollar med
     style="--section-space:0". Defaulten ar en clamp: natt pa mobil, generos pa desktop. */
  /* CONTENT-GUTTER (best practice): huvudinnehallsregionen ramas in med luft pa ALLA sidor. Golvet gav forr bara padding-block till main>section (inget inline-gutter alls, block bara nar innehall lag i en <section>) -> innehall klistrade mot vanster OCH topp. Nu far main-regionen en responsiv gutter, VIKTBAR via --w-space (Builder AI:s override; calc DIREKT i regeln, ej nastlad i token per bug B). --content-gutter-x/y overrider exakt varde; data-full-bleed / --content-gutter-*:0 nollar. */ :where(main, .app-shell > [data-region=m], .app-shell > [data-region=main]) { padding-inline: calc(var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem)) * var(--w-space, 1)); padding-block: calc(var(--content-gutter-y, clamp(1.5rem, 3.5vw, 2.75rem)) * var(--w-space, 1)); } /* CONTENT-MAX (proportionell layout, best practice): pa breda skarmar sprawlade innehallet obegransat (uppmatt: 2480px brett @2560px vp, gutter fast 40px). Kapa innehallet vid en bekvam bredd och centrera sa MARGINALERNA VAXER proportionerligt pa stora skarmar i stallet for att innehallet strackts ut. Plain <main> (landningssidor) kapas; app-shell-regioner (data-region) lamnas FULLA — dashboards vill ha bredden. --content-max tunar (80rem default). Verifierat via headless-render 1280/1920/2560: innehall stilla 1200px, marginal 40->680px, ingen h-scroll. */ :where(main:not([data-region])) { max-inline-size: var(--content-max, 80rem); margin-inline: auto; } /* SIDNIVA FOOTER/HEADER-GUTTER: golvet gav main en inline-gutter, men en sidniva-footer/header (syskon till main, EJ .bar) fick ingen -> innehallet klistrade mot vanster/hoger kant (uppmatt: Atelier-footern, brand + copyright mot bagge kanterna, 0 inline-inset). Ger en topp-niva footer/header samma --content-gutter-x som main sa allt linjerar mot samma kant. Exkluderar .bar (chrome med egen padding), data-full-bleed (kant-till-kant med flit), app-shell-regioner (data-region, egen layout), och footer/header NASTLAD i innehall (descendant av main/section/article/card/panel) sa bara sidnivan traffas. Ociterade attributselektorer (JS-strang-sakert). --content-gutter-x tunar. */ :where(footer, header):not(.bar):not([data-full-bleed]):not([data-region]):not(:where(main, section, article, .card, .panel, .app-shell) *) { padding-inline: calc(max(var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem)), (100% - var(--content-max, 80rem)) / 2 + var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem))) * var(--w-space, 1)); } /* APP-SHELL CONTENT-FOOTER/HEADER-GUTTER: en footer/header som ar en app-shell-REGION (data-region=f/h) och INTE chrome (.bar/.rail) fick ingen inline-gutter — main-guttern traffar bara [data-region=m], och sidniva-regeln ovan exkluderar [data-region]. Sa innehallet lag flush mot kanten medan main var indraget. Ger content-footer/header samma gutter som main sa allt linjerar. */ :where(.app-shell > [data-region=f], .app-shell > [data-region=footer], .app-shell > [data-region=h], .app-shell > [data-region=header]):not(.bar):not(.rail):not([data-full-bleed]) { padding-inline: calc(var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem)) * var(--w-space, 1)); } /* Sektioner: regionens gutter ger yttre ramen, sa sektioner behover bara MELLANRUM (inter-section), ej egen ytterpadding (annars dubbel). :where() sa .pad-y/--section-space:0 vinner. */ :where(main > section + section) { margin-block-start: var(--section-space, clamp(2rem, 4vw, 3.5rem)); } /* FULL-BLEED BAND (opt-in): data-full-bleed bryter ut ur guttern till kant-till-kant, ateradderar inline-padding sa innehallet halls gutter-linjerat, far egen block-rytm och nuddar grannar (band-monstret bevarat som opt-in). Forsta/sista bandet drar ut aven i block sa hero nuddar toppen. */ :where(main > [data-full-bleed]) { margin-inline: calc(-1 * var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem))); padding-inline: var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem)); padding-block: var(--band-space, clamp(2.5rem, 5vw, 5rem)); margin-block-start: 0; } :where(main > [data-full-bleed]:first-child) { margin-block-start: calc(-1 * var(--content-gutter-y, clamp(1.5rem, 3.5vw, 2.75rem))); } :where(main > [data-full-bleed]:last-child) { margin-block-end: calc(-1 * var(--content-gutter-y, clamp(1.5rem, 3.5vw, 2.75rem))); } /* BAND EFTER INNEHALL: ett full-bleed-band som foljer ett ICKE-band (vanlig sektion/kort) ska ha luft ovanfor, annars klistrar bandet mot innehallet (uppmatt: vitt OM-band direkt mot funktions-korten, 0 topp-inset). full-bleed-regeln ovan spikar margin-block-start:0 pa ALLA band (sa band nuddar band, ratt) men skiljer inte pa band-efter-band och band-efter-innehall. Den har regeln kraver prev = ICKE-band, sa band-mot-band nuddar fortfarande (OM->CTA), och forsta bandet (:first-child, ingen foregangare) far sin negativa bleed orord. Ligger EFTER margin-block-start:0 sa den vinner pa kallordning (bada :where()=noll spec); --section-space (eller :0) tunar/nollar precis som sektion-rytmen. */ :where(main > :not([data-full-bleed]) + [data-full-bleed]) { margin-block-start: var(--section-space, clamp(2rem, 4vw, 3.5rem)); } /* FULL-BLEED I CAPAD MAIN: nar plain <main> kapas av --content-max maste ett band bryta ut till VIEWPORT-kanten (ej bara -gutter, som forutsatter full-bredds-main). 100vw + margin-inline:calc(50% - 50vw) centrerar bandet pa viewporten oavsett mainens capade bredd; padding-inline aterstaller sa bandets innehall linjerar med det capade innehallet. Bara plain main (app-shell-main ar ej capad → bas-regelns -gutter galler dar). Verifierat 1280/1920/2560: band 0->vw, innehall i linje, ingen h-scroll. */ :where(main:not([data-region]) > [data-full-bleed]) { inline-size: 100vw; margin-inline: calc(50% - 50vw); padding-inline: calc(max(0px, (100vw - var(--content-max, 80rem)) / 2) + var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem))); }
  /* Containerkontext sa komponenter kan anpassa sig efter YTAN, inte fonstret */
  .app-shell > [data-region], .card, .panel, .grid > *, .stack, main { container-type: inline-size; } /* CONTAINER-TYPE KOLLAPS-SKYDD: container-type:inline-size (ovan, for stat container-queries) gor elementets inre storlek innehalls-oberoende. Nar ett sadant element ar ett flex/grid-BARN med auto inline-marginaler (t.ex. en centrerad panel med max-width + margin:0 auto) shrink-to-fittar det, containment ger 0, och texten rasar till ETT tecken per rad (samma falla som center-fixen men for alla container-type-element). inline-size:stretch far dem att FYLLA foraldern som ett vanligt block; max-inline-size kappar och auto-marginaler centrerar. :where()=noll spec sa forfattarens egen bredd vinner. Enhetsfallbacks for aldre browsers. */ :where(.card, .panel, .stack, .grid > *, main, .app-shell > [data-region]) { inline-size: -webkit-fill-available; inline-size: -moz-available; inline-size: stretch; }

  /* ── FULL BREDD AR KONTEXTBEROENDE, inte en egenskap hos kontrollen ──────\
     Uppmatt drift: golvet spikade inline-size:100%% pa .nav-item OCH pa\
     input/select/textarea. Det gav en DRAGNING MOT VERTIKALT: en top-nav\
     staplade (varje lank tog full bredd i en flex-rad), och en sok-toolbar\
     (input+select+knapp i .cluster) staplade likasa. Men full bredd ar RATT i\
     en KOLUMN (formulal, sidorail) och FEL i en RAD (toolbar, top-nav). En\
     kontroll vet inte sitt sammanhang — FORALDERN gor det. Sa defaulten ar nu\
     auto (inneboende bredd), och KOLUMN-containrar delar ut full bredd till sina\
     kontroll-/nav-barn. Rad-containrar (.cluster/.toolbar/horisontell .nav) lamnar\
     dem auto. Formulal och etiketter ar naturligt staplade → full bredd dar med. */\
  .stack > :where(input, textarea, select),\
  form > :where(input, textarea, select),\
  :where(label) > :where(input, textarea, select),\
  .field > :where(input, textarea, select) { inline-size: 100%; }\
  .rail .nav-item, .rail a, .nav[data-vertical] .nav-item, .nav[data-vertical] a,\
  .rail .nav, .stack > .nav[data-vertical] { inline-size: 100%; }\
  /* Rad-containrar: nav-item och kontroll haller sin inneboende bredd med FLIT,\
     sa raden inte staplas. (Redundant med auto-defaulten men explicit mot arv.) */\
  .cluster > :where(input, textarea, select, .nav-item),\
  .toolbar > :where(input, textarea, select, .nav-item) { inline-size: auto; } /* FORM-LAYOUT: formularfalt i ett responsivt rutnat (max 2 kolumner, kollapsar till 1 pa smalt). Handrullade formular fick smala/utspridda falt — falt i wrapper-divar foll till auto-bredd och tvafalts-rader spreds med space-between. Nu: varje .field fyller sin kolumn (label ovan kontroll), och breda falt (data-span/textarea/fieldset/.form-actions) spanner hela raden. .field ar aven fristaende (utan .form-grid) en ren label+kontroll-grupp. */ .form-grid { display: grid; gap: var(--form-gap, var(--space-md, 1rem)); grid-template-columns: repeat(auto-fit, minmax(max(var(--form-col, 14rem), calc(50% - var(--form-gap, 1rem))), 1fr)); align-items: start; } .field { display: flex; flex-direction: column; gap: var(--space-2xs, .25rem); min-inline-size: 0; } .field > label { margin: 0; } .field > :where(input, textarea, select, .cluster, .toolbar) { inline-size: 100%; } .form-grid > :where(textarea, fieldset, .form-actions, [data-span]) { grid-column: 1 / -1; }
}

@layer eontra.components {
  /* ── Ytor ───────────────────────────────────────────────────────────── */
  /* Fem primitiver rorde chrome-tokens som ingenting laste, och --on-gradient
       fanns men knappen anvande --on-primary aven pa gradient. */
    .badge, .tag, .chip, .avatar { box-shadow: var(--shadow-sm, none); }
    [data-modal] > *, .popover, [popover] { box-shadow: var(--shadow-popover, none); }
    .surface, .panel, .card {
    /* PRINCIP: varje primitiv ar ALLTID kopplad. Glas och Gradient far darfor
       inte bero pa att modellen satter en klass. background-color bar glaset
       (som vid 0 ar var(--surface), alltsa regionens ton), background-image bar
       gradienten (som vid 0 ar none). De ar SKILDA egenskaper och samsas. */
    background-color: var(--glass-bg, var(--surface));
    background-image: var(--gradient-surface, none);
    box-shadow: var(--elevation-edge, 0 0 transparent), var(--shadow-card, none);
    transition: box-shadow calc(var(--transition-base, .2s) * var(--motion-scale, 1)) ease, border-color calc(var(--transition-base, .2s) * var(--motion-scale, 1)) ease;
    
    border: calc(var(--border-width, 1px) * var(--w-border, 1)) var(--border-style, solid) var(--border);
    border-radius: calc((var(--radius-lg, var(--radius, .75rem))) * var(--radius-scale, 1));
  }
  .card, .panel { padding: calc(var(--pad, var(--space-lg)) * var(--w-space, 1)); background-color: var(--panel-bg, var(--glass-bg, var(--surface))); box-shadow: var(--panel-shadow, var(--shadow-card, none)); color: var(--panel-text, var(--text)); border-color: var(--panel-border, var(--border)); border-radius: var(--panel-radius, calc((var(--radius-lg, var(--radius, .75rem))) * var(--radius-scale, 1))); }
  .card { display: flex; flex-direction: column; gap: var(--space-sm); color: var(--card-text, var(--text)); }
  .card[data-interactive], a.card, button.card {
    cursor: pointer; text-align: start; text-decoration: none; color: inherit;
    transition: transform calc(var(--transition-fast, .18s) * var(--motion-scale, 1)) var(--ease-standard, ease),
                box-shadow calc(var(--transition-fast, .18s) * var(--motion-scale, 1)), border-color calc(var(--transition-fast, .18s) * var(--motion-scale, 1));
  }
  .card[data-interactive]:hover, a.card:hover, button.card:hover {
    transform: translateY(calc(var(--hover-lift, 3px) * var(--w-motion, 1) * -1));
    box-shadow: var(--shadow-raised, 0 6px 20px rgb(0 0 0 / .1));
    border-color: color-mix(in srgb, var(--primary) 25%, var(--border));
  }
  .card > :where(h1,h2,h3,h4,h5,h6) { margin: 0; }
  .card > :where(p) { margin: 0; color: var(--muted); font-size: var(--font-size-small, .9rem); }
  .card-media { margin: calc(var(--pad, var(--space-lg)) * -1); margin-block-end: 0; border-start-start-radius: inherit; border-start-end-radius: inherit; overflow: hidden; }
  /* data-flush laser som en allman modifierare men fanns bara pa .panel.
     Uppmatt: ett bygge skrev <div class="card" data-flush> pa tre stallen for
     att fa tabellen kant i kant — attributet gjorde ingenting och kortet behold
     sin padding. Ett attribut som ser generellt ut maste bete sig generellt. */
  .panel[data-flush], .card[data-flush] { padding: 0; overflow: hidden; }
  .glass { background: var(--glass-bg, color-mix(in srgb, var(--surface) 70%, transparent)); backdrop-filter: blur(var(--glass-blur, 12px)); }

  /* ── Chrome: header / sidebar / footer ──────────────────────────────── */
  .bar {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-md); padding-block: var(--space-sm); padding-inline: calc(var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem)) * var(--w-space, 1));
    background-color: var(--glass-bg, var(--surface));
    background-image: var(--chrome-accent, none);
    backdrop-filter: blur(var(--glass-blur, 0px)); border-block-end: 1px solid var(--border);

    box-shadow: var(--chrome-shadow, 0 2px 4px rgba(0,0,0,0.07));
    border-radius: var(--chrome-radius, 0);
    /* CHROME-MARGINAL: floating chrome (radie) MASTE ha luft runtom annars ser det lossnat ut (rundat kant-i-kant = bakgrunds-ficka i hornet). --chrome-margin ar 0 for bar (kant-till-kant) och en inset for floating — deriveras men applicerades aldrig forr. */
    margin: var(--chrome-margin, 0);
  }
  .bar[data-sticky] { position: sticky; inset-block-start: 0; z-index: 50; } /* BAR PAD-TO-CAP: en page-level .bar (ej i app-shell) ska halla sitt innehall i linje med det --content-max-capade mainen pa breda skarmar. Baren forblir full-bredd (bakgrund/kant spanner viewporten) men paddingen vaxer sa brand/nav landar pa samma kant som main/footer. Bars I en app-shell (dashboard-header/botten-nav) lamnas pa gutter — appen ar full-bredd. Verifierat 1280/1920/2560: brand linjerar med main/footer (40->680px). */ .bar:not(.app-shell *) { padding-inline: calc(max(var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem)), (100% - var(--content-max, 80rem)) / 2 + var(--content-gutter-x, clamp(1rem, 3.5vw, 2.5rem))) * var(--w-space, 1)); }
  /* SCROLL-ELEVATION: en sticky topp-bar fordjupar sin skugga nar sidan scrollas (polish som AI:n annars hand-rullar med en scroll-lyssnare). Ren CSS via scroll-timeline, INGET JS. @supports-gated → browsers utan scroll-timeline behaller barens statiska skugga (graceful). @media reduced-motion hoppar over. Botten-bar (data-bottom) berors ej. */
  @supports (animation-timeline: scroll()) { @media (prefers-reduced-motion: no-preference) { .bar[data-sticky]:not([data-bottom]) { animation: eontra-bar-elevate linear both; animation-timeline: scroll(root block); animation-range: 0 6rem; } @keyframes eontra-bar-elevate { from { box-shadow: var(--chrome-shadow, 0 2px 4px rgba(0,0,0,0.07)); } to { box-shadow: var(--shadow-raised, 0 4px 16px rgb(0 0 0 / .12)); } } } }
  .bar[data-bottom] { border-block-start: 1px solid var(--border); border-block-end: 0; } /* BOTTEN-NAV: en data-bottom-bar med data-sticky ska fastna i BOTTEN, inte toppen. .bar[data-sticky] satter inset-block-start:0; overrida for botten-varianten. */ .bar[data-bottom][data-sticky] { inset-block-start: auto; inset-block-end: 0; } /* STICKY RAIL (opt-in, best practice for sidopanels-nav): data-sticky pa en .rail haller sidomenyn synlig medan main scrollar (root-scroll-modell). align-self:start = railen far sin egen hojd (ej strackt till main:s) och fastnar i toppen; egen scroll nar nav ar langre an skarmen. Speglar .bar[data-sticky]. Finns en TOPP-sticky .bar i shellen (holy-grail) satts --chrome-top till barens hojd sa railen fastnar UNDER baren, inte under den. --chrome-top / --bar-block-size tunar. */ .app-shell:has(> .bar[data-sticky]:not([data-bottom])) { --chrome-top: var(--bar-block-size, 3.5rem); } .rail[data-sticky] { position: sticky; inset-block-start: var(--chrome-top, 0); align-self: start; max-block-size: calc(100dvh - var(--chrome-top, 0px)); overflow-y: auto; }
  .rail {
    display: flex; flex-direction: column; gap: var(--space-2xs, .25rem);
    padding: var(--space-lg) var(--space-md); background-color: var(--glass-bg, var(--sidebar-bg, var(--surface))); color: var(--sidebar-text, var(--text));
    background-image: var(--chrome-accent, none);
    backdrop-filter: blur(var(--glass-blur, 0px));
    border-inline-end: 1px solid var(--border);
    box-shadow: var(--chrome-shadow, 2px 0 4px rgba(0,0,0,0.05));
    border-radius: var(--chrome-radius, 0);
    margin: var(--chrome-margin, 0);
    overflow-y: auto; min-block-size: 0; }
  .rail[data-edge="start"] { border-inline-end: var(--chrome-border, 1px solid var(--border)); }
  .rail[data-edge="end"]   { border-inline-start: var(--chrome-border, 1px solid var(--border)); } /* RAIL-WIDGET-SPACING: rail-gapet (space-2xs) ar kalibrerat for TATA nav-items. Bar railen WIDGETS (card/panel/section/stack) blir det for trangt — de far luft mellan sig sa de laser som separata widgets, inte hopklibbade. Nav-items rors ej. */ .rail > :where(.card, .panel, section, .stack):not(:first-child) { margin-block-start: var(--space-md); }
  .brand {
    display: inline-flex; align-items: center; gap: var(--space-sm);
    font-family: var(--font-heading, var(--font-family)); font-weight: 800;
    font-size: var(--font-size-large, 1.15rem); color: var(--primary-readable, var(--primary));
    letter-spacing: -.02em; text-decoration: none;
  }
  /* HAMBURGER: .nav-toggle ar knappen som oppnar mobil-drawern. Dold pa desktop, syns nar sidomenyn kollapsar (<40rem). Lagg den i .bar; SDK:n Eontra.nav.toggleDrawer wirar den. */
  .nav-toggle { display: none; }
  .nav-toggle { padding: var(--space-xs); background: none; border: 0; cursor: pointer; color: inherit; border-radius: calc((var(--radius-sm, .3rem)) * var(--radius-scale, 1)); }
  .nav-toggle svg { inline-size: 1.5rem; block-size: 1.5rem; }
    .brand-mark { inline-size: .5rem; block-size: .5rem; border-radius: var(--radius-full, 999px); background: var(--accent, var(--primary)); flex: none; } .brand-mark:empty:not([data-dot]) { display: none; } /* TITEL-TRUNKERING: en lang brand/titel i en .bar wrappade baren till flera rader (white-space:normal). Trunkera med ellips + min-inline-size:0 sa den KRYMPER forst (atgarder behaller sin storlek, min-width:auto) och baren haller EN rad. */ :where(.bar .brand) { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* Atgardssidan i en .bar ska INTE wrappa/krympa — annars staplar den sina knappar vertikalt och gor baren flerradig nar titeln ar lang. Halls kompakt sa BRANDEN absorberar krympningen (trunkerar). */ :where(.bar > .cluster, .bar > .toolbar) { flex-wrap: nowrap; flex-shrink: 0; }
  .eyebrow {
    font-size: var(--font-size-small, .72rem); font-weight: 700; text-transform: uppercase;
    letter-spacing: .08em; color: var(--muted);
  }

  /* ── Navigation ─────────────────────────────────────────────────────── */
  .nav { display: flex; gap: var(--space-2xs, .25rem); flex-wrap: wrap; }
  .nav[data-vertical] { flex-direction: column; flex-wrap: nowrap; }
  /* HORISONTELL TOPBAR-MENY: en <ul>/<li>-meny i en horisontell bar/header staplade vertikalt (floret nollade markorer men lat <li> vara block-niva). En meny i en topbar ar horisontell precis som nav-primitiven; rail/aside/vertikal nav samt nastlade undermenyer (li *) forblir kolumn. --nav-gap finjusterar. */
  :where(.bar, .topbar, .navbar, .app-header, header, .header, [role=banner], [role=menubar]):not([data-vertical]):not(.rail):not(.sidebar) :where(ul, ol):not([data-vertical]):not(.stack):not(li *) { display: flex; flex-wrap: wrap; align-items: center; gap: var(--nav-gap, var(--space-2xs, .25rem)); }
  :where(.bar, .topbar, .navbar, .app-header, header, .header, [role=banner], [role=menubar]):not([data-vertical]):not(.rail):not(.sidebar) :where(ul, ol):not([data-vertical]):not(.stack):not(li *) > li { margin-block: 0; } /* NAKET <nav> MED DIREKTA LANKAR: ovan gor en <ul>/<ol>-meny horisontell, men den vanliga semantiska markupen ar ett naket <nav> med .nav-item/<a> DIREKT (ingen lista). Da forblev <nav> block och varje .nav-item (som ar display:flex) blev en blocknivarad -> lankarna staplade vertikalt (uppmatt: topbar Funktioner/Om/Kontakt pa var sin rad). En <nav> ar horisontell precis som nav-primitiven; :has(> lankar) traffar bara nar nav BAR direkta interaktiva barn (ej nar den omsluter en <ul>, som redan hanteras), och rail/aside/sidoregioner + data-vertical/stack exkluderas sa vertikala navs forblir kolumn. Ociterade attributvarden med flit (JS-strang-sakert). --nav-gap finjusterar. */ nav:not([data-vertical]):not(.rail):not(.stack):not(:where(.rail, aside, .sidebar, [data-region=l], [data-region=r], [data-region=left], [data-region=right]) *):has(> :where(a, .nav-item, button)) { display: flex; flex-wrap: wrap; align-items: center; gap: var(--nav-gap, var(--space-2xs, .25rem)); }
  .nav-item, .rail a, .nav a {
    transition: background calc(var(--transition-base, .2s) * var(--motion-scale, 1)) ease, color calc(var(--transition-base, .2s) * var(--motion-scale, 1)) ease;
    display: flex; align-items: center; gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    border-radius: calc((var(--radius-md, var(--radius, .5rem))) * var(--radius-scale, 1));
    color: var(--text); text-decoration: none; font-weight: 500;
    font-size: var(--font-size-body, 1rem); line-height: 1.2;
    background: none; border: 0; cursor: pointer; text-align: start;
    transition: background calc(var(--transition-fast, .15s) * var(--motion-scale, 1)), color calc(var(--transition-fast, .15s) * var(--motion-scale, 1));
  }
  .nav-item:hover, .rail a:hover, .nav a:hover {
    background: var(--accent-surface, color-mix(in srgb, var(--primary) 8%, transparent));
    color: var(--on-accent-surface, var(--primary-readable, var(--primary)));
  }
  .nav-item[aria-current], .rail a[aria-current], .nav a[aria-current], nav a[aria-current], [role=navigation] a[aria-current], [role=menubar] a[aria-current],
  .nav-item.is-active, .rail a.is-active, .nav a.is-active, nav a.is-active, [role=navigation] a.is-active, [role=menubar] a.is-active,
  .nav-item.active, .rail a.active, .nav a.active, nav a.active, [role=navigation] a.active, [role=menubar] a.active {
    background: var(--primary); color: var(--on-primary, #fff);
  }
  .nav-item svg, .rail a svg { inline-size: 1.15em; block-size: 1.15em; flex: none; opacity: .75; }
  .nav-item[aria-current] svg { opacity: 1; } /* TRAILING i nav-item: ett count/badge/tag (eller [data-trailing]) som SISTA barn puttas till hoger kant (Inbox 3-monstret) i stallet for att klistra efter etiketten. */ :where(.nav-item, .rail a, .nav a) > :where(.badge, .tag, [data-trailing]):last-child { margin-inline-start: auto; }
  .breadcrumb { display: flex; flex-wrap: wrap; gap: var(--space-xs); align-items: center; font-size: var(--font-size-small, .875rem); color: var(--muted); }
  .breadcrumb > * + *::before { content: "/"; margin-inline-end: var(--space-xs); opacity: .5; }
  .tabs { display: flex; gap: var(--space-xs); border-block-end: 1px solid var(--border); overflow-x: auto; scrollbar-width: thin; }
  .tabs > * {
    padding: var(--space-sm) var(--space-md); background: none; border: 0;
    border-block-end: 2px solid transparent; color: var(--muted);
    font-weight: 600; cursor: pointer; border-radius: 0;
  }
  .tabs > [aria-selected="true"], .tabs > .is-active, .tabs > .active, .tabs > [aria-current] { color: var(--tab-active-color, var(--primary-readable, var(--primary))); border-block-end-color: var(--tab-indicator, var(--primary)); }
}


@layer eontra.components {
  /* ── Data & status ──────────────────────────────────────────────────── */
  .badge, .tag, .chip {
    display: inline-flex; align-items: center; gap: var(--space-2xs, .25rem);
    padding: .15em .6em; border-radius: calc((var(--radius-sm, .3rem)) * var(--radius-scale, 1));
    background: var(--badge-bg, var(--accent-surface, color-mix(in srgb, var(--primary) 10%, transparent)));
    color: var(--badge-text, var(--text));
    font-size: var(--font-size-small, .75rem); font-weight: 600; line-height: 1.6;
    white-space: nowrap;
  }
  .badge[data-tone="success"] { background: var(--success-bg, color-mix(in srgb, var(--success, green) 14%, transparent)); color: var(--success-text, var(--success, green)); }
  .badge[data-tone="warning"] { background: var(--warning-bg, color-mix(in srgb, var(--warning, orange) 16%, transparent)); color: var(--warning-text, var(--warning, orange)); }
  .badge[data-tone="danger"]  { background: var(--danger-bg,  color-mix(in srgb, var(--danger, crimson) 12%, transparent)); color: var(--danger-text, var(--danger, crimson)); }
  .badge[data-tone="info"]    { background: var(--info-bg,    color-mix(in srgb, var(--info, steelblue) 12%, transparent)); color: var(--info-text, var(--info, steelblue)); }
  .badge[data-tone="neutral"] { background: color-mix(in srgb, var(--muted) 14%, transparent); color: var(--muted); } .badge[data-variant="secondary"], .tag[data-variant="secondary"] { background: var(--secondary); color: var(--on-secondary, var(--on-primary)); }
  .dot { inline-size: .5rem; block-size: .5rem; border-radius: var(--radius-full, 999px); background: currentColor; flex: none; vertical-align: middle; margin-inline: .15rem; overflow: hidden; } .dot[data-tone="success"] { background: var(--success, green); } .dot[data-tone="warning"] { background: var(--warning, orange); } .dot[data-tone="danger"] { background: var(--danger, crimson); } .dot[data-tone="info"] { background: var(--info, steelblue); } .dot[data-tone="neutral"] { background: var(--muted); }

  .stat { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-sm); padding-block: var(--space-xs); }
  .stat-label { color: var(--muted); font-size: var(--font-size-small, .875rem); }
  .stat-value { font-family: var(--font-mono, ui-monospace, monospace); font-weight: 700; font-variant-numeric: tabular-nums; }
  .metric { display: flex; flex-direction: column; gap: var(--space-2xs, .25rem); }
  .metric-value { font-family: var(--font-heading, var(--font-family)); font-size: var(--font-size-display, clamp(1.6rem, 1.1rem + 2vw, 2.4rem)); font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
  .metric-label { color: var(--muted); font-size: var(--font-size-small, .85rem); }

  .list { display: flex; flex-direction: column; }
  /* flex-wrap ar barande: raden ar en flex-container, sa VARJE direkt barn blir
     ett flex-objekt. Renderar appen flera textelement som syskon i samma rad
     konkurrerar de om bredden och pressas till min-content — alltsa ett ORD per
     rad. Uppmatt i en driftoversikt: badge, typ, tjanst och beskrivning som fyra
     syskon gav en oläsbar spalt trots 1 280 px ledigt utrymme. Med wrap bryter
     raden i stallet nar innehallet inte far plats, vilket ar det man menar. */
  .list > * { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-sm); padding-block: var(--space-sm); border-block-end: 1px solid var(--border); }
  .list > :last-child { border-block-end: 0; }
  .list[data-hover] > *:hover { background: var(--accent-surface, color-mix(in srgb, var(--primary) 5%, transparent)); }

  .avatar {
    inline-size: var(--size, 2.5rem); block-size: var(--size, 2.5rem); flex: none;
    border-radius: var(--radius-full, 999px); object-fit: cover;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--accent-surface, color-mix(in srgb, var(--primary) 12%, transparent));
    color: var(--on-accent-surface, var(--primary)); font-weight: 700;
  }
  .avatar-group { display: flex; }
  .avatar-group > .avatar + .avatar { margin-inline-start: -.65rem; box-shadow: 0 0 0 2px var(--surface); }

  .alert {
    display: flex; gap: var(--space-sm); padding: var(--space-md);
    border-radius: calc((var(--radius, .5rem)) * var(--radius-scale, 1)); border: 1px solid var(--border);
    background: var(--surface);
  }
  .alert[data-tone="success"] { border-color: var(--success, green); background: var(--success-bg, transparent); }
  .alert[data-tone="warning"] { border-color: var(--warning, orange); background: var(--warning-bg, transparent); }
  .alert[data-tone="danger"]  { border-color: var(--danger, crimson); background: var(--danger-bg, transparent); }
  .alert[data-tone="info"]    { border-color: var(--info, steelblue); background: var(--info-bg, transparent); }

  .empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-sm); padding: var(--space-2xl) var(--space-lg); text-align: center; color: var(--muted); }
  .empty > :where(h1,h2,h3,h4) { color: var(--text); }

  .toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-sm); }
  .toolbar > .spacer, .spacer { margin-inline-start: auto; } /* .spacer var horisontell (margin-inline-start:auto). I en KOLUMN-container (rail/stack/vertikal nav) ska den putta VERTIKALT — sa en sidopanels-footer (userMeny/loggaut) pinnas till botten med <span class=spacer></span>. */ :where(.rail, .stack, .nav[data-vertical]) > .spacer { margin-block-start: auto; margin-inline-start: 0; }
  .divider { border-block-start: 1px solid var(--border); margin-block: var(--space-md); }
  .divider[data-vertical] { border-block-start: 0; border-inline-start: var(--chrome-border, 1px solid var(--border)); margin: 0 var(--space-sm); align-self: stretch; }

  .btn[data-variant="secondary"], .btn-secondary {
    background: var(--surface); color: var(--text); border-color: var(--border);
  }
  .btn[data-variant="secondary"]:hover, .btn-secondary:hover { border-color: var(--primary); color: var(--primary-readable, var(--primary)); }
  .btn[data-variant="ghost"], .btn-ghost { background: none; color: var(--text); border-color: transparent; box-shadow: none; }
  .btn[data-variant="ghost"]:hover, .btn-ghost:hover { background: var(--accent-surface, color-mix(in srgb, var(--primary) 8%, transparent)); box-shadow: none; }
  .btn[data-variant="danger"] { background: var(--danger, crimson); color: var(--on-danger, #fff); }
  .btn[data-variant="outline"], .btn-outline { background: none; color: var(--primary-readable, var(--primary)); border-color: currentColor; box-shadow: none; }
  .btn[data-variant="outline"]:hover, .btn-outline:hover { background: var(--accent-surface, color-mix(in srgb, var(--primary) 8%, transparent)); }
  .btn[data-size="sm"] { padding: var(--space-2xs, .3rem) var(--space-sm); font-size: var(--font-size-small, .85rem); }
  .btn[data-size="lg"] { padding: var(--space-md) var(--space-xl); font-size: var(--font-size-large, 1.1rem); }
  .btn[data-icon] { padding: var(--space-sm); aspect-ratio: 1; }

  .skeleton {
    background: linear-gradient(90deg,
      color-mix(in srgb, var(--muted) 12%, transparent) 25%,
      color-mix(in srgb, var(--muted) 22%, transparent) 37%,
      color-mix(in srgb, var(--muted) 12%, transparent) 63%);
    background-size: 400% 100%;
    animation: eontra-shimmer 1.4s ease-in-out infinite;
    border-radius: calc((var(--radius-sm, .3rem)) * var(--radius-scale, 1)); color: transparent; user-select: none;
    min-block-size: 1em;
  }
  @keyframes eontra-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
  @keyframes eontra-spin { to { transform: rotate(360deg); } } @keyframes eontra-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
}

@layer eontra.components {
  /* ── FORMAXLAR ────────────────────────────────────────────────────────
     Golvet bestamde tidigare KOMPONENTERNAS FORM: ett kort var alltid kantat
     och rundat, ett aktivt navval alltid en fylld platta. Koordinaten flyttade
     bara VARDEN. Tva appar kunde darfor skilja sig i varje token och anda lasa
     som samma produkt. Reglerna nedan lasar formen ur tokens i stallet.
     Varje var() har DAGENS varde som fallback — ett tema utan formaxlar
     (aldre projekt, direkta token-overrides) renderar exakt som forut.
     Ligger sist i lagret sa de vinner pa lika specificitet. */
  .card {
    background-color: var(--card-bg, var(--glass-bg, var(--surface)));
    border: var(--card-border, calc(var(--border-width, 1px) * var(--w-border, 1)) var(--border-style, solid) var(--border));
    border-width: calc(var(--card-border-width, var(--border-width, 1px)) * var(--w-border, 1));
    /* KOMPONENT-VIKT: radien och paddingen multipliceras med en per-komponent-vikt
       (--w-radius, --w-space), default 1 = oforandrat. Ett kort kan da lokalt bara
       style="--w-radius:1.6" for rundare horn UTAN att koordinatens roundness rors
       och UTAN egen CSS. Samma mekanik som skuggans --shadow-scale. Skalar, ersatter
       inte: en vikt gor mer/mindre av en befintlig axel, aldrig en ny egenskap. */
    border-radius: calc((calc(var(--card-radius, var(--radius-lg, var(--radius, .75rem))) * var(--w-radius, 1))) * var(--radius-scale, 1));
    box-shadow: var(--elevation-edge, 0 0 transparent), var(--card-shadow, var(--shadow-card, none));
  }
  .nav-item[aria-current], .rail a[aria-current], .nav a[aria-current], nav a[aria-current], [role=navigation] a[aria-current], [role=menubar] a[aria-current],
  .nav-item.is-active, .rail a.is-active, .nav a.is-active, nav a.is-active, [role=navigation] a.is-active, [role=menubar] a.is-active,
  .nav-item.active, .rail a.active, .nav a.active, nav a.active, [role=navigation] a.active, [role=menubar] a.active {
    background: var(--nav-active-bg, var(--primary));
    color: var(--nav-active-color, var(--on-primary, #fff));
    box-shadow: var(--nav-active-edge, none);
    font-weight: var(--nav-active-weight, 500);
  }
  .list > * { border-block-end: var(--divider-line, 1px solid var(--border)); padding-block: calc(var(--space-sm) + var(--divider-gap, 0px)); }
  .list > :nth-child(even) { background: var(--divider-alt-bg, transparent); }
  .list > :last-child { border-block-end: 0; }
  :where(th, td) { border-block-end: var(--divider-line, 1px solid var(--border)); }
  :where(tbody tr:nth-child(even)) { background: var(--divider-alt-bg, transparent); color: var(--divider-alt-text, var(--text)); }
  :where(tbody tr:last-child td) { border-block-end: 0; }
  /* Etikett-axeln ror BARA de ytor som redan ar versala idag (eyebrow,
     tabellhuvuden). .stat-label/.metric-label lamnas ororda med flit: de har
     ingen sparrning idag, och en default pa .06em hade andrat utseendet for
     alla befintliga appar — defaulten maste vara dagens. */
  /* ── TYPOGRAFISK ROST (type_emphasis) ──────────────────────────────────
     Golvet spikade vikten pa nitton stallen: varumarket 800, eyebrow 700,
     navval 500, flikar 600, brickor 600, stat 700, metric 800, knappar 600.
     Koordinaten flyttade typsnitt, storleksskala och rubrikvikt men aldrig
     dessa, sa varje app fick samma fetma-personlighet oavsett brief. Rollerna
     behaller sin inbordes ordning; axeln flyttar hela ackordet. Fallbacken ar
     dagens varde, sa ett tema utan axeln renderar oforandrat. */
  .brand { font-weight: var(--weight-brand, 800); }
  .eyebrow { font-weight: var(--weight-eyebrow, 700); }
  .nav-item, .rail a, .nav a { font-weight: var(--weight-nav, 500); }
  .tabs > * { font-weight: var(--weight-control, 600); flex-shrink: 0; }
  .badge, .tag, .chip { font-weight: var(--weight-badge, 600); }
  .stat-value, .avatar { font-weight: calc(var(--weight-value, 700) * var(--w-text, 1)); }
  .metric-value { font-weight: calc(var(--weight-display, 800) * var(--w-text, 1)); }
  :where(button, .btn, [type="button"], [type="submit"], [type="reset"]) { font-weight: var(--weight-control, 600); }
  :where(strong, b) { font-weight: var(--weight-strong, 700); }
  :where(thead th) { font-weight: var(--weight-strong, 700); }
  :where(label):not(:has(input[type="checkbox"], input[type="radio"])), :where(summary), :where(legend) { font-weight: var(--weight-control, 600); }
  /* Det AKTIVA navvalet styrs av nav_active och far inte overkoras har —
     regeln nedan ligger senare i lagret och vinner darfor pa lika specificitet. */
  .eyebrow, :where(thead th) {
    text-transform: var(--label-transform, uppercase);
    letter-spacing: var(--label-tracking, .06em);
    font-family: var(--label-family, inherit);
  }
}

@layer eontra.state {
  /* TRAFFYTE-GOLV: interaktiva element sattes tidigare enbart av padding, utan minsta hojd. Uppmatt foll knappar/nav/flikar till 27-37px vid hog density - over WCAG 2.5.8-golvet 24px men under 44px-malet. min-block-size GARANTERAR tappbar hojd (padding vaxer, krymper aldrig under golvet). Pa touch (pointer: coarse) hojs golvet till 44px. :where() haller specificiteten noll. */
  :where(button, .btn, [type="button"], [type="submit"], [type="reset"], .nav-item, .rail a, .nav a, .tabs > *, summary) { min-block-size: var(--tap-min, 2rem); }
  :where(input:not([type="checkbox"]):not([type="radio"]), select) { min-block-size: var(--tap-min, 2rem); }
  :where(:focus-visible) {
    outline: 2px solid var(--primary-readable, var(--primary));
    outline-offset: 2px;
    border-radius: calc((var(--radius-sm, .25rem)) * var(--radius-scale, 1));
  }
  :where(:focus:not(:focus-visible)) { outline: none; }
  [hidden], .is-hidden { display: none !important; }
  [aria-busy="true"] { cursor: progress; }
  [aria-disabled="true"], :disabled { opacity: .55; cursor: not-allowed; }
    /* LADDNING: .is-loading var ihalig (bara pointer-events). Nu spinner-overlay + dampat innehall.
     .spinner ar fristaende. --spinner-size/--spinner-color lokaljusterar. Reduced-motion stannar
     rotationen (global *-regel) → statisk ring, fortfarande tydlig markor. */
  .is-loading { position: relative; pointer-events: none; }
  .is-loading > * { opacity: .5; }
  .is-loading::after {
    content: ""; position: absolute; inset-block-start: 50%; inset-inline-start: 50%;
    inline-size: var(--spinner-size, 1.5rem); block-size: var(--spinner-size, 1.5rem);
    margin-block-start: calc(var(--spinner-size, 1.5rem) / -2);
    margin-inline-start: calc(var(--spinner-size, 1.5rem) / -2);
    border: 2px solid color-mix(in srgb, var(--spinner-color, var(--primary)) 25%, transparent);
    border-block-start-color: var(--spinner-color, var(--primary));
    border-radius: var(--radius-full, 999px);
    animation: eontra-spin .7s linear infinite;
  }
  .spinner {
    display: inline-block; vertical-align: -.15em;
    inline-size: var(--spinner-size, 1.25rem); block-size: var(--spinner-size, 1.25rem);
    border: 2px solid color-mix(in srgb, var(--spinner-color, var(--primary)) 25%, transparent);
    border-block-start-color: var(--spinner-color, var(--primary));
    border-radius: var(--radius-full, 999px);
    animation: eontra-spin .7s linear infinite;
  }
  ::-webkit-scrollbar { inline-size: 10px; block-size: 10px; }
  ::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 35%, transparent); border-radius: 999px; }
  ::-webkit-scrollbar-track { background: transparent; }
  html { scrollbar-color: color-mix(in srgb, var(--muted) 35%, transparent) transparent; scrollbar-width: thin; }
  /* ANKAR-SCROLL UNDER STICKY HEADER: en fast .bar[data-sticky] (topp) doljer annars ett ankar-mal nar man klickar en in-sid-lank (malet scrollar in UNDER headern). scroll-padding pa root-scrollern haller malet under baren. Bara nar en TOPP-sticky bar finns (:has) → sidor utan sticky header far ingen offset. --scroll-offset tunar (default 5rem tacker typisk header + andrum); botten-sticky (data-bottom) triggar inte. */
  html:has(.bar[data-sticky]:not([data-bottom])) { scroll-padding-block-start: var(--scroll-offset, 5rem); }
}

@layer eontra.utility {
  .sr-only {
    position: absolute; inline-size: 1px; block-size: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  .skip-link { position: absolute; inset-block-start: -100%; inset-inline-start: 0; z-index: 999; padding: var(--space-sm) var(--space-md); background: var(--primary); color: var(--on-primary, #fff); }
  .skip-link:focus { inset-block-start: 0; }
  .muted { color: var(--muted); } .text-sm { font-size: var(--font-size-small); } .text-lg { font-size: var(--font-size-large); }
.text-xs { font-size: var(--font-size-small); }
.text-xl { font-size: var(--font-size-large); } .text-label { font-size: var(--font-size-label); } .text-display { font-size: var(--font-size-display); }
  .truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .clamp { display: -webkit-box; -webkit-line-clamp: var(--lines, 2); -webkit-box-orient: vertical; overflow: hidden; }
  .full { inline-size: 100%; }
  .scroll-y { overflow-y: auto; min-block-size: 0; }
  :where(.app-shell) :empty:not(input, textarea, img, svg, br, hr, td, th, .dot, .skeleton, .avatar, .brand-mark, .spacer, [data-calendar] *) { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  @layer eontra.state {
    *, *::before, *::after {
      animation-duration: .01ms !important; animation-iteration-count: 1 !important;
      transition-duration: .01ms !important; scroll-behavior: auto !important;
    }
    :where(.card, .btn, button):hover { transform: none !important; } .marquee-track { animation: none !important; transform: none !important; } .marquee { overflow-x: auto; }
  }
}

@media (forced-colors: active) {
  @layer eontra.state {
    .card, .panel, .surface, .bar, .rail { border: 1px solid CanvasText; }
    :where(:focus-visible) { outline: 2px solid Highlight; }
  }
}

@media (pointer: coarse) {
  @layer eontra.state {
    /* Touch: lyft traffyte-golvet till 44px (Apple HIG / WCAG 2.5.5 forbattrat) dar fingret behover det. */
    :root { --tap-min: 2.75rem; }
  }
}

@container (max-width: 30rem) {
  .stat { flex-direction: column; align-items: flex-start; gap: 0; }
}

@media (max-width: 60rem) {
  @layer eontra.layout {
    .app-shell[data-collapse] { grid-template-areas: var(--areas-md, var(--areas)); grid-template-columns: var(--cols-md, var(--cols, 1fr)); }
  }
}
@media (max-width: 40rem) {
  @layer eontra.layout {
    .app-shell[data-collapse] { grid-template-areas: var(--areas-sm, none); grid-template-columns: var(--cols-sm, 1fr); grid-template-rows: var(--rows-sm, none); } .app-shell[data-collapse] > [data-region] { align-self: start; } /* Sticky rail neutraliseras nar shellen staplar (annars fastnar full-bredds-railen over innehallet). */ .rail[data-sticky] { position: static; max-block-size: none; } /* KROSS-SKYDD: en app-shell utan data-collapse (byggd med t.ex. --areas:"l m" men ingen responsiv variant) lat forr en fast sidopanel krossa main till en olasbar sliver pa smal skarm (uppmatt: 220px rail @360px vy -> main 140px -> text bryts ord for ord). Nu staplar aven en icke-collapse app-shell till en kolumn <40rem sa main alltid far last bredd. Opt-out med data-no-stack. Respekterar appens egna --cols-sm/--areas-sm om satta. */ .app-shell:not([data-collapse]):not([data-no-stack]) { grid-template-areas: var(--areas-sm, none); grid-template-columns: var(--cols-sm, 1fr); grid-template-rows: var(--rows-sm, none); } .app-shell:not([data-collapse]):not([data-no-stack]) > [data-region] { grid-area: var(--region-sm, auto); align-self: start; }
    /* REGIONSTINT: atmosfaren som ytfarg. Bakgrundslagret ligger bakom allt och syns bara i rannorna — uppmatt tacker skalet 71 %% av viewporten med opaka ytor, och standardkompositionernas moln ligger EXAKT dar chromet ligger. Harledningen samplar molnfaltet per region och ger en solid ton; har omdefinieras --surface inom regionen, sa bar/rail/card arver sin zons ton UTAN att andras. Faller alltid tillbaka pa --surface-base, som emitteras aven utan atmosfar. */ .app-shell > [data-region="h"], .app-shell > [data-region="header"] { --surface: var(--surface-h, var(--surface-base)); } .app-shell > [data-region="l"], .app-shell > [data-region="left"] { --surface: var(--surface-l, var(--surface-base)); } .app-shell > [data-region="m"], .app-shell > [data-region="main"] { --surface: var(--surface-m, var(--surface-base)); } .app-shell > [data-region="r"], .app-shell > [data-region="right"] { --surface: var(--surface-r, var(--surface-base)); } .app-shell > [data-region="f"], .app-shell > [data-region="footer"] { --surface: var(--surface-f, var(--surface-base)); } .app-shell[data-collapse] > [data-region="left"], .app-shell[data-collapse] > [data-region="right"],
    .app-shell[data-collapse] > [data-region="l"], .app-shell[data-collapse] > [data-region="r"] { display: none; }
  }
  @layer eontra.components { /* .bar mobil-override borttagen: bas-regelns content-gutter-clamp (floor 1rem) haller alignmentet mot main/footer aven pa mobil; en space-md-override gjorde baren tightare an innehallet. */ }
  @layer eontra.components { .app-shell[data-collapse][data-drawer] .nav-toggle { display: inline-flex; align-items: center; justify-content: center; } }
  /* KOLLAPS-FIX: hide-regeln ovan ligger i @layer eontra.layout, men .rail sätter display:flex i
     eontra.components (senare lager → vinner), så en rail-baserad sidomeny kollapsade ALDRIG. En OSKIKTAD
     regel slår alla lager oavsett ordning (kaskad-spec: unlayered > layered). Nu döljs sidomenyn
     faktiskt vid <40rem när app-shell bär data-collapse. */
  .app-shell[data-collapse] > [data-region="left"], .app-shell[data-collapse] > [data-region="right"],
  .app-shell[data-collapse] > [data-region="l"], .app-shell[data-collapse] > [data-region="r"] { display: none; }
  /* MOBIL DRAWER: en kollapsad sidomeny forsvinner pa mobil — utan vag tillbaka ar navet oatkomligt. Opt-in med data-drawer pa app-shell: sidomenyn blir en off-canvas panel som glider in nar data-drawer-open satts (Eontra.nav.toggleDrawer sköter attributet). .nav-toggle ar hamburger-knappen. Utan data-drawer galler vanliga display:none-kollapsen ovan. */
  .app-shell[data-collapse][data-drawer] > [data-region="left"],
  .app-shell[data-collapse][data-drawer] > [data-region="l"],
  .app-shell[data-collapse][data-drawer] > [data-region="right"],
  .app-shell[data-collapse][data-drawer] > [data-region="r"] {
    display: flex; position: fixed; inset-block: 0; inset-inline-start: 0; z-index: 200;
    inline-size: min(80vw, var(--drawer-width, 17rem)); max-inline-size: 85vw;
    transform: translateX(-102%); transition: transform var(--transition-base, .25s) var(--ease-standard, ease);
    overflow-y: auto; box-shadow: var(--drawer-shadow, var(--shadow-modal, 0 0 40px rgb(0 0 0 / .3)));
  }
  .app-shell[data-collapse][data-drawer][data-drawer-open] > [data-region="left"],
  .app-shell[data-collapse][data-drawer][data-drawer-open] > [data-region="l"],
  .app-shell[data-collapse][data-drawer][data-drawer-open] > [data-region="right"],
  .app-shell[data-collapse][data-drawer][data-drawer-open] > [data-region="r"] { transform: none; }
  .app-shell[data-drawer][data-drawer-open]::after { content: ""; position: fixed; inset: 0; z-index: 199; background: rgb(0 0 0 / .45); }\
}

/* ── STATE-OF-THE-ART-POLISH (default, best practice, degraderar rent) ── Progressiva finish-tekniker golvet garanterar sa AI:n slipper. Feature-detekterat/ignorerbart → utan stod ser ut som forr; reduced-motion nollar rorelse. */ :where(.btn, button, .nav-item, .tabs > *, .badge, .tag, .chip, .brand, .eyebrow, .stat-value, .metric-value) { text-box: trim-both cap alphabetic; } :where(blockquote, p) { hanging-punctuation: first allow-end last; } .bar { box-shadow: var(--elevation-edge, 0 0 transparent), var(--chrome-shadow, 0 2px 4px rgba(0,0,0,0.07)); } @keyframes eontra-pop-in { from { opacity: 0; transform: translateY(6px) scale(.985); } } :where(dialog)[open] { animation: eontra-pop-in var(--transition-base, .25s) var(--ease-emphasized, cubic-bezier(.2,0,0,1)) both; } :where([popover]):popover-open { animation: eontra-pop-in var(--transition-fast, .18s) var(--ease-standard, ease) both; } @view-transition { navigation: auto; } ::view-transition-old(root), ::view-transition-new(root) { animation-duration: var(--transition-base, .28s); animation-timing-function: var(--ease-standard, ease); } @media (prefers-reduced-motion: reduce) { ::view-transition-old(root), ::view-transition-new(root) { animation: none; } } /* AXEL-BINDNINGAR: OSKIKTADE med flit. Golvets vanliga regler ligger i @layer eontra.*, och per kaskad-spec slar en forfattares OSKIKTADE style-regel ALLTID en skiktad regel aven pa lagre specificitet. Uppmatt: modellen skrev .btn-primary { background: var(--primary) } i eget style-block och skuggade golvets gradient-bindning, sa reglaget gjorde ingenting fast tokens uppdaterades. Dessa bindningar KOPPLAR en koordinat-axel till en yta; skuggas de tystnar ett reglage. De ligger OSKIKTADE och sist (vinner pa kallordning) och ar attribut-burna (ett snapp over en bar klass). Enda platsen golvet medvetet gar utanfor lager-systemet, bara for axel-kritiska bindningar. */ .btn[data-variant="primary"], .btn.btn-primary { background: var(--gradient-primary, var(--primary)); color: var(--on-gradient, var(--on-primary, #fff)); } .surface[class], .panel[class], .card[class] { background-image: var(--gradient-surface, none); } .nav-item[aria-current], .rail a[aria-current], .nav a[aria-current], nav a[aria-current], [role=navigation] a[aria-current], [role=menubar] a[aria-current], .nav-item.is-active, .rail a.is-active, .nav a.is-active, nav a.is-active, [role=navigation] a.is-active, [role=menubar] a.is-active, .nav-item.active, .rail a.active, .nav a.active, nav a.active, [role=navigation] a.active, [role=menubar] a.active { background: var(--nav-active-bg, var(--primary)); color: var(--nav-active-color, var(--on-primary, #fff)); }
