/* Piece A: nav and hero. Layout per elia-design.md band model. */

/* The hero's mandated radial lives on <body>, which is the only surface BEHIND
   the field's canvas. Put on .hero-zone it painted over the canvas -- .hero-zone
   is inside main, and main is z-index 1 -- and hid the field completely.
   Same ellipse, same stops, same tokens; it is anchored to the top of the
   document so it still sits behind the hero and nowhere else. */
body {
  background-image:
    radial-gradient(ellipse 70% 55vh at 50% 40vh,
                    var(--color-ink-elevated) 0%, transparent 78%);
  background-repeat: no-repeat;
  background-attachment: fixed;
}

/* ---- The brain ----
   A fixed full-screen WebGL2 canvas behind every band, carrying the 3D
   wireframe mesh. Mechanism 1 of bar-field.md still holds: the canvas never
   moves when the page scrolls -- the OBJECT turns instead -- and no pointer
   event ever lands on it. The page's own Ink is behind it, on <body>; the
   canvas clears transparent and composites over it. */
.brain {
  position: fixed;
  inset: 0;
  /* ABOVE main, not below it. Ruling AR(c).

     The object used to sit at 0 with main at 1, which put every page element
     on top of it -- including the waveform, whose 180px band scrolls up
     through a canvas that does not move. MEASURED: 30 of the 56 bars painted
     over the object at 25%, 50% and 75% of the hero.

     Raising the canvas above main is safe because the canvas is TRANSPARENT
     everywhere the object is not drawn, and the object is drawn only in the
     hero band and fades out below it. Everything the object must never cover
     -- the hero copy, the call cards -- is raised back above it explicitly.
     Everything else is decoration or is far below the object's reach, and
     composites against transparent pixels. The highest z-index anywhere inside
     main was 1, so nothing else in the page had an opinion about this. */
  z-index: 2;
  display: block;
  pointer-events: none;
  /* A canvas is a replaced element: with width auto its layout size is the
     BACKING STORE, not the inset. Without these two the element measured
     whatever canvas.width last was, and since resize() is debounced every
     viewport change spent 160ms painting a wrongly-sized projection. */
  width: 100%;
  height: 100%;
  /* The nav is transparent over the hero by spec and its links are Ink Mist,
     the one pair on this page with no contrast headroom -- 4.79:1, 0.29 above
     the floor. Rather than amend the nav rule, the field simply is not drawn
     behind the bar: it fades in below it. */
  /* The nav fade and the hero text-column fade both used to live here as CSS
     masks. They now live in the field's own fragment shader instead, because a
     CSS mask is applied by the compositor and is therefore invisible to
     readPixels: the contrast probe that ruling AK(f) requires would have been
     measuring an image the viewer never sees, and reporting failures it could
     not verify. In the shader the measurement is ground truth.

     The brain needs NEITHER mask. It is a single object confined to the right
     column by its own fit, so it is never behind the headline and never under
     the nav; there is nothing left to suppress. Ruling AQ(d). See
     tools/contrast-probe.js, which still gates it. */
}
/* main keeps its containing block and LOSES its stacking context. With
   z-index: 1 it trapped every descendant below the canvas or above it as one
   block, so the waveform could not go behind the object while the copy stayed
   in front of it. Without it, the two are free to sit on either side. */
main, .footer { position: relative; }
/* The two things the object may never cover, raised explicitly above it.
   Their order relative to each other is unchanged: the copy stays above the
   cards, as it has been since they were verified never to intersect. */
/* THE CARDS ARRIVE ON THE RIGHT, and they are laid out against the object's
   own solved position rather than beside a fixed column. Ruling AR(d).

   --brain-cards-left-px is where js/brain.js measured the object's right edge
   to land once it has finished travelling, plus its clearance. --cards-lead-px
   is the empty flow that keeps the cards BELOW the object's band until it has
   travelled far enough left for them to fit beside it.

   Both fall back to nothing, so with the script absent this is the centred
   band it was before. */
.hero-cards { position: relative; z-index: 3; }
.hero-centre { z-index: 4; }

/* ---- THE LAYER LABELS -------------------------------------------------
   The five layer names, placed around the object while it crosses the hero.

   FIXED, in viewport coordinates, for the same reason the canvas is: the
   object's projected position is a viewport position, and a label that
   scrolled would have to be re-solved against the object at every offset
   instead of once per resize. Their boxes are written once per layout and
   never change afterwards, so nothing on the page moves as they arrive --
   only their opacity, and (ruling AX) their own 16px lift as each comes in.

   z-index 3, level with the cards, below the copy and above the canvas.
   Under ruling AX the lowest name may sit on the object, and there the order
   IS exercised: the name paints over the wireframe, not under it.

   pointer-events none on the container: this is annotation over a canvas that
   answers the cursor, and a label swallowing pointermove would leave a dead
   rectangle in the object's own interaction. */
.brain-labels {
  position: fixed;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}
.brain-label {
  /* THE SAME SETTING AS .layer-eyebrow, and that is the point. These are the
     same five strings the stack band sets 1500px further down. A reader meets
     ELIA VOICE twice on this page and it has to be the same object both
     times, so the face, size, tracking and weight are taken from there rather
     than chosen again here. */
  position: absolute;
  margin: 0;
  white-space: nowrap;
  /* Everything about the face comes from .mono, which the element carries,
     and that is the point rather than an economy. .mono is where the
     html[lang] rule lives: English labels take +0.06em, Turkish +0.02em,
     because uppercase Turkish at English label tracking collides its own
     diacritics. Restating the properties here without the class -- which is
     what this rule did first -- pinned the floating labels to +0.06em in both
     locales, so ELIA PRIVATE AI set 128.7px in the hero and 120.9px in the
     stack band on the same Turkish page. Same string, same page, two settings.
     Only the size and weight are restated, because .mono's own micro size is
     smaller than the stack band's eyebrow. */
  /* THE SIZE IS SOLVED. --label-px is written by solveLabels() in js/brain.js:
     the largest size at which all five names still have a legal place round
     the object at this viewport. The owner asked for title scale -- a box of
     the order of 620x250 at 1440 -- and what that scale can actually be is a
     question about the room left round a 900px object, so it is answered by
     the same search that places them. The fallback is the stack band's
     eyebrow size, which is what they were before. */
  font-size: var(--label-px, var(--text-mono-sm));
  line-height: 1.12;
  font-weight: var(--weight-regular);
  /* NO EMBER, and this is the budget rather than a preference. The countable
     list is closed at nine types with a ceiling of three per viewport, and the
     hero already spends all three on the filled CTA, the live status dot with
     its ping ring, and the waveform. The accent rule settles it independently:
     an Ember element must be an action or a live state, and a layer name is a
     classification. Five accent labels around an accent-lit object would also
     be the exact failure the owner named. */
  /* SAND, the page's secondary text colour on dark, not Ink Mist. These are
     content -- the names of the five things the object is -- and this page
     runs two colour axes: a warm one for content (the hero eyebrow, the body
     copy and the call cards are all Sand) and a cool one for chrome (the nav
     links are Ink Mist). Set in Ink Mist the labels read as chrome parked over
     the artwork, and a critic named the hue mismatch against the call-card
     text 40px away. --text-on-dark-secondary is the token for exactly this
     job. The ruling that took Sand off eyebrows applies to 11px eyebrows
     sitting BESIDE Ember, where Sand reads as a second accent; these are 13px
     and the nearest Ember is the object's own edges, 48px away and behind
     them. The hero's own eyebrow is Sand on this same surface. */
  color: var(--text-on-dark-secondary);
  opacity: 0;
  /* No transition. The opacity is driven from the scroll position frame by
     frame in js/brain.js, so a CSS transition would fight it and lag the
     object it is annotating. */
}
/* All five in Sand (owner, 2026-09-06). Voice was Linen -- the page's
   primary/secondary step carrying "the one layer in production", ruling AV --
   and the owner asked for the five to match. The stack band's Sahada badge
   still carries the deployment state. */
.brain-label.is-live { color: var(--text-on-dark-secondary); }
/* ELIA on the first line, the layer name on the second. */
.brain-label span { display: block; }

/* The labels belong to the object. Where the object is not drawn, they are
   not drawn either -- ruling AJ's threshold, inherited the same way. */
@media (max-width: 1179.98px) {
  .brain-labels { display: none; }
}

/* Below 900 the object is not drawn at all. Ruling AJ set that threshold for
   the object it authorised and this object inherits it: the phone hero is
   governed by ruling P -- one call card below the CTA, the waveform yielding
   the fold to it -- and there is no fold budget there for a decorative object.
   The build had 700 here, which drew it at 768 and 899 where the ruling says
   it is not drawn. */
/* Raised from 900 to 1100 with ruling AN(c). The brain now gets its own column
   and the hero's text moves out of its way, and that only works while the row
   is wide enough to hold both. MEASURED across the field-visible range: at
   1100x800 the object's left edge lands at 39.7% of the viewport, leaving 373px
   for the text column, which still carries the display headline. At 1000x800 it
   leaves 279px and at 900x900 only 110px, which cannot. Below 1100 there is no
   arrangement where the brain is both drawn and clear of the headline, and
   drawing it UNDER the headline is the exact fault this ruling removes. */
/* Raised again, 1100 -> 1180, with ruling AR(e). The object now travels and
   the cards now take a right-hand column, and BOTH of those stop at 1180:
   below it, css/site.css's own @media (max-width: 1179.98px) turns the card
   band into a centred column with an OPAQUE Ink background, which would paint
   flat over the object at every scroll offset. Two further measurements say
   the same thing -- at 1085 usable width the object's rest window leaves the
   headline 308px, under the 373px ruling AN(c) certified as the floor, and the
   card column plus the object no longer both fit beside each other.
   1180 is where the card layout changes, so it is where the object stops. */
/* WITHDRAWN, ruling AY (owner, 2026-09-07): the object IS drawn below 1180.
   The hero there is one centred column, so the object takes the column --
   js/brain.js fits it to the page's full width, rests it under the nav and
   sends it straight down as the page scrolls -- and it sits BEHIND the copy
   (canvas z 2, .hero-centre z 4) at this opacity: "yazıların arkasında daha
   şeffaf saydam bir şekilde". The names stay off below 1180; there is no
   room around a full-width object for five of them. The card band below the
   hero gives up its opaque Ink for the same reason (see the responsive
   block): a fixed object behind a band that paints flat over it would be
   wiped by the band's edge as it scrolls up. */
@media (max-width: 1179.98px) {
  .brain { opacity: var(--brain-mobile-alpha, 0.5); }
  /* And BEHIND every band after the hero, not only the copy. The canvas is
     z 2 above main (ruling AR(c)); at the park the object stands at the
     foot of the frame, and the next band's headline scrolls in from the
     bottom straight into it -- MEASURED at 375x812, "Yapay Zeka
     Çözümlerimiz" inside the object's box from p 0.73, painted UNDER the
     wireframe. Raised to the cards' level, the bands' text is over the
     object as the copy is, and the desktop's fade stands. Their
     backgrounds are unchanged: the dark bands are transparent, so the
     object shows through them; the light ones are opaque and far below
     the object's reach. */
  .hero-zone ~ section, .footer { position: relative; z-index: 3; }
}

/* WHERE THE FIELD MAY SHOW, and the arithmetic behind it.

   Ink Mist on Ink is 4.79:1 -- 0.29 above the AA floor, and the tightest
   certified pair on this page. Measured, the field's brightest composited
   background is L=0.066 against Ink's 0.013, which drops Ink Mist text to
   2.5:1. For Ink Mist to survive the field would have to raise the background
   by less than 0.002 in luminance, which is another way of saying it would
   have to be invisible. Linen clears at 7.9:1 and Sand at 5.5:1.

   The hero is the only band whose text is Linen and Sand alone, so the hero is
   the only band that goes transparent. Every other dark band keeps its Ink.
   The object still travels on scroll; below the hero it is occluded rather
   than showing through six bands of muted metadata.

   Round 1 made every dark band transparent and the system critic measured the
   result: 71.3% of one Proof-band paragraph below 4.5:1, worst point 1.00:1.
   That is what this rule exists to prevent. */
/* Ruling AH moves in the SAFE direction here: the hero eyebrow and subhead
   were certified against the withdrawn gradient's Ink Elevated core at 8.47:1
   and now sit on Ink at 10.45:1. */

/* ---- Nav ---- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px var(--gutter);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background var(--dur-base) var(--ease-signal),
              border-color var(--dur-base) var(--ease-signal);
}
.nav.scrolled {
  /* Ruling I: solid. 92 percent opacity ghosts light-band text through the bar. */
  background: var(--color-ink);
  border-bottom-color: var(--color-ink-line);
}
.nav-left { display: flex; align-items: center; gap: 12px; }
.nav-wordmark { font-size: 18px; }
/* THE OWNER'S LOGO, ruling AZ (2026-09-07): img/logo-v3-on-ink.png in the
   nav and the footer, where the live-text wordmark was -- the on-Ink
   variant, ELI in Linen (img/logo-v3.png is the supplied colourway, for
   light surfaces). An image after all, against
   the Wordmark note below: the owner supplied the artwork as the new logo.
   Sized by height so the lockup keeps its own proportions; the intrinsic
   width/height attributes hold the box before the file lands. */
.nav-logo { display: block; line-height: 0; }
.nav-logo img { display: block; height: 28px; width: auto; }
.footer-logo { display: block; height: 22px; width: auto; }

/* ---- Wordmark ----
   Live text in the display face, never an image: it stays sharp at every pixel
   density and changes colour by register instead of by asset swap.

   Two tone, faithful to the supplied artwork, which is navy and SAND. Ember
   is deliberately absent from the mark, for two independent reasons:
     - on Linen, Ember letters are 2.73:1 and ruling F bans them outright;
     - on Ink, an Ember wordmark would be a FOURTH Ember element type, against
       a ceiling of three that the hero already fills (CTA, live status,
       waveform). The mark's own bars do not count, per ruling O.
   Sand carries the AI on dark in its documented role as warm secondary text.
   On light Sand is 1.43:1 and banned, so Ink Slate takes it at 6.52:1, the
   same substitution the status pill already makes for its complete state. */
.wordmark {
  line-height: 1.36;   /* the display family's own floor; it was inheriting body 1.60 */
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  /* Positive, so no Turkish tracking rule is touched. An uppercase lockup
     needs air where the sentence-case wordmark wanted -0.006em. */
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.wm-eli { color: var(--color-linen); }
/* Weight carries the split where tone alone did not read at nav size. */
.wm-ai  { color: var(--color-sand); font-weight: var(--weight-semi); }

/* The light register. The nav is NOT one of these: ruling I made the scrolled
   bar solid Ink, so the nav wordmark sits on Ink at every scroll position. */
.on-light .wm-eli { color: var(--color-ink); }
.on-light .wm-ai  { color: var(--color-ink-slate); }
.nav-links { display: flex; gap: 8px; }
.nav-link {
  font-family: var(--font-body);
  font-size: 15px;               /* system: navigation Inter 500, 14-15px */
  font-weight: var(--weight-medium);
  letter-spacing: 0;             /* system: navigation tracking 0 */
  color: var(--color-ink-mist);
  text-decoration: none;
  padding: 0 16px;
  line-height: 40px;
  transition: color var(--dur-fast) var(--ease-signal);
}
.nav-link:hover { color: var(--color-linen); }
.nav-right { display: flex; align-items: center; gap: 20px; }

/* ---- Mobile navigation ----
   Below 900px .nav-links is display:none and, until 2026-08-28, nothing
   replaced it. At 360 this document is 15,618px, twenty-one viewports, and
   it is precisely the width the page is forwarded to when the buyer sends it
   on to procurement and IT. A page that long with no wayfinding is the worst
   single finding of the Impeccable review.

   No keyframe is introduced. A disclosure encodes a state that is currently
   true, which is the argument .faq-a already makes under the motion law.

   Closed, the panel is visibility:hidden, NOT merely zero-height. A zero-height
   panel keeps its links in the tab order and in the accessibility tree while
   the button reports aria-expanded="false", which is the same contradiction the
   FAQ carried and which is being fixed in the same pass. */

/* ---- Skip link ----
   Hidden until focused. Ink Elevated with a hairline, exactly as every other
   raised surface on dark; no shadow. */
.skip-link {
  position: absolute;
  top: -200px;
  left: var(--gutter);
  z-index: 60;
  padding: 12px 16px;
  background: var(--color-ink-elevated);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
  color: var(--color-linen);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: var(--weight-medium);
  letter-spacing: 0.005em;
  text-decoration: none;
}
.skip-link:focus-visible {
  top: 12px;
  outline: 2px solid var(--color-ember);
  outline-offset: 2px;
}
/* main takes focus from the skip link without becoming a tab stop. */
#main:focus { outline: none; }

/* ---- Focus coverage ----
   14 of 29 focusable elements carried no author :focus-visible rule and fell
   back to the UA default ring, which on a near-black navy canvas is close to
   invisible. The four selectors that already had one were the exception, not
   the pattern. Same Ember ring; Ember is 5.48:1 on Ink and 6.36:1 on the
   footer's Ink Deep, both clear of the 3:1 floor for a focus indicator. */
.nav-link:focus-visible,
.faq-mail:focus-visible,
.footer-col a:focus-visible,
a.footer-fact-id:focus-visible {
  outline: 2px solid var(--color-ember);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
/* The button and the panel's contents are styled UNCONDITIONALLY and only their
   display is breakpoint-scoped. Held inside the media query, .nav-panel-link had
   no rule at all above 900px and computed the UA's default link blue at 1.81:1
   on Ink -- invisible today only because the panel is display:none there, which
   is a latent defect one rule away from shipping. Look here, visibility below. */
.nav-menu-btn {
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: var(--spacing-8);
  padding: 0;
  background: none;
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
  color: var(--color-ink-mist);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-signal),
              border-color var(--dur-fast) var(--ease-signal);
}
.nav-menu-btn svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.25;
  stroke-linecap: round;
}
.nav-menu-btn:hover { color: var(--color-linen); border-color: var(--color-ink-slate); }
.nav-menu-btn:focus-visible { outline: 2px solid var(--color-ember); outline-offset: 2px; }

.nav-panel-inner { min-height: 0; overflow: hidden; }
.nav-panel-link {
  display: block;
  padding: 0 var(--gutter);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: var(--weight-medium);
  letter-spacing: 0.005em;
  line-height: 48px;
  color: var(--color-ink-mist);
  text-decoration: none;
  border-top: 1px solid var(--color-ink-line);
  transition: color var(--dur-fast) var(--ease-signal);
}
.nav-panel-link:hover { color: var(--color-linen); }
.nav-panel-link:focus-visible { outline: 2px solid var(--color-ember); outline-offset: -2px; }

.nav-menu-btn { display: none; }
.nav-panel { display: none; }

@media (max-width: 900px) {
  .nav-menu-btn { display: inline-flex; }

  .nav-panel {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    display: grid;
    grid-template-rows: 0fr;
    visibility: hidden;
    overflow: hidden;
    background: var(--color-ink);
    border-bottom: 1px solid transparent;
    /* visibility is a DISCRETE property. Transitioned over the full duration it
       flips mid-collapse, so the panel reads hidden while it is still open.
       The idiom is a zero-length transition DELAYED by the duration on close,
       and undelayed on open: visible the instant it opens, and still visible
       for the whole of the collapse. */
    transition: grid-template-rows var(--dur-base) var(--ease-signal),
                visibility 0s linear var(--dur-base),
                border-color var(--dur-base) var(--ease-signal);
  }
  .nav.is-menu-open .nav-panel {
    grid-template-rows: 1fr;
    visibility: visible;
    border-bottom-color: var(--color-ink-line);
    transition: grid-template-rows var(--dur-base) var(--ease-signal),
                visibility 0s linear 0s,
                border-color var(--dur-base) var(--ease-signal);
  }
  /* The bar goes solid while the panel is open, so a transparent bar over the
     hero does not leave the panel floating off nothing. Ruling I's reasoning. */
  .nav.is-menu-open { background: var(--color-ink); border-bottom-color: var(--color-ink-line); }

}

/* The toggle lives in the bar above 480 and in the panel below it. At 320 the
   bar has 2.3px of slack, so the menu button cannot be added without freeing
   the toggle's width. AMENDS ruling B's collapse list, which read
   "mark, wordmark, language toggle, CTA": the toggle is still present at every
   width, it moves into the panel rather than leaving the page. */
.nav-panel .lang-toggle { display: none; }
@media (max-width: 480px) {
  .nav-right .lang-toggle { display: none; }
  .nav-panel .lang-toggle { display: flex; margin: var(--spacing-16) var(--gutter); }
}

.lang-toggle {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  line-height: var(--leading-micro);
  letter-spacing: var(--tracking-micro);
  font-weight: var(--weight-medium);
}
/* The two locales are real buttons now, not spans. They were decoration that
   looked like a control; a control that does nothing is worse than no control.
   Everything below is the button element being talked back down to the text it
   already looked like -- no fill, no border, no padding, the toggle's own mono
   type inherited -- so the rendered result is byte-identical to the spans it
   replaces at rest. */
.lang-opt {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: 0;
  margin: 0;
  padding: 0;
  font: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}
.lang-toggle .active   { color: var(--color-linen); }
/* Ink Mist at 4.80:1, not Ink Slate at 2.30:1. The exemption that allowed
   2.30:1 reasoned that the inactive locale was "a disabled affordance rather
   than text a reader must read". It is a <button> with tabindex 0 that
   switches the site's language -- an actionable control, and for a reader who
   does not read Turkish it is the ONE control on the page they need. See the
   amended exemption in elia-design.md. */
.lang-toggle .inactive { color: var(--color-ink-mist); }
.lang-opt.inactive:hover { color: var(--color-linen); transition: color var(--dur-fast) var(--ease-signal); }
/* Focus rings are transient and mutually exclusive, so they cost no Ember. */
.lang-opt:focus-visible { outline: 2px solid var(--color-ember); outline-offset: 2px; }
.lang-toggle .rule { width: 1px; height: 10px; background: var(--color-ink-line); }


/* ---- Buttons ---- */
.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-8);
  background: var(--accent);
  color: var(--accent-label);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: var(--weight-semi);
  letter-spacing: 0.005em;
  border: none;
  border-radius: var(--radius-md);
  padding: 13px 22px;
  min-width: 132px;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-signal);
}
.btn-primary:hover  { background: var(--accent-hover); }
.btn-primary:active { background: var(--accent-active); }
.btn-primary:focus-visible { outline: 2px solid var(--color-ember); outline-offset: 2px; }

/* ---- Light-register focus ring ----
   elia-design.md's Focus rings rule has mandated this since it was written and
   it was never built: "On the light register Ember only reaches 2.73:1 against
   Linen and fails the 3:1 non text requirement, so the light register uses a
   2px Ink outline with a 1px Ember inner line."

   Measured before this rule existed: every :focus-visible on the page drew the
   dark-register Ember ring, including the CTA inside #randevu, which sits on
   Linen. Ember on Linen is 2.73:1 against WCAG 1.4.11's 3:1 floor for a focus
   indicator. Ink on Linen is 14.98:1.

   The inner line is drawn with box-shadow because a border would shift layout
   and a second outline does not exist. That is SIGNAL, not elevation, exactly
   as the live dot's glow is, and the no-shadow rule is about depth. Focus
   rings do not count against the Ember budget: they are transient and only one
   can exist at a time, which elia-design.md already states. */
.on-light a:focus-visible,
.on-light button:focus-visible,
.on-light summary:focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 2px;
  box-shadow: 0 0 0 1px var(--color-ember);
}
/* No nav variant: the primary CTA renders identically everywhere, per spec. */

/* ---- Hero ----
   Height is the viewport, exactly. The waveform band is pinned to the
   hero's bottom, so it is pinned to the rendered fold at every breakpoint.
   Content centres in the zone ABOVE the band via the bottom padding. */
/* THREE COLUMNS. The hero is a left card column, a centre text column and a
   right card column, all three derived from the same two numbers on the
   ancestor both descend from. Text lives only in the centre, cards only at
   the sides, so overlap is impossible rather than merely avoided.

   The arithmetic, and why the gap is exact: the centre is centred inside the
   hero's content box, so its right edge lands at
       inset + contentW - (card + gap)
   while the right card's left edge lands at
       inset + contentW - card
   and the difference is --card-gap, at every width, with no drift. */
.hero-zone {
  position: relative;
  --card-w: 340px;
  --card-inset: var(--gutter);
  --card-gap: var(--spacing-48);
  --hero-centre-w: 100%;   /* one column until the viewport can hold three */

  /* The diagonal. Each column is offset from the one before it so the eye
     travels top right, then centre, then lower left. --hero-drop pushes the
     centre column below true centre; the cards take the two extremes. */
  --hero-drop: 0px;
  --card-live-top: 16vh;

  /* The band's height, and the gap the hero's content keeps above it. Declared
     once, because this number was written out four times -- the band, the
     hero's bottom reserve, the completed card's anchor, and again at two
     breakpoints -- and a reserve equal to the band leaves the tallest bar tip
     landing flush on the CTA's bottom edge. The clearance is what makes "never
     crossed" visible rather than merely true to the pixel. */
  --wave-h: 180px;
  --wave-clear: var(--spacing-48);
}
.hero {
  position: relative;
  /* min-height, never height. The centre column plus the waveform's 180px
     reserve needs 789px of hero. At a fixed 100vh anything shorter than that
     made the centred column overflow SYMMETRICALLY, so its lower half landed
     inside the reserve and the bars painted over the CTA. The hero grows
     instead: the reserve is never entered at any width or height, and on a
     viewport below 789px the waveform's faded tail goes under the fold.
     The 640px floor is deleted rather than beaten -- two min-heights in one
     rule is the cascade defect, and 640 could not hold the content anyway. */
  min-height: 100vh;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* The gradient is MANDATED in three places -- the Waveform Hero component,
     band model item 1 and the Agent Prompt Guide -- so it is not deleted. It
     moves to .hero-zone, which sits BEHIND the field's canvas, so the hero
     keeps its documented atmosphere and the field still reads on top of it
     rather than being covered by it. */
  overflow: hidden;
  padding: 96px var(--gutter) calc(var(--wave-h) + var(--wave-clear));
}
/* The centre column, and the headline's sizing container: the display size
   is a function of THIS column's width, not the viewport's, so the headline
   always fills its own column and never has to be capped against a card. */
.hero-centre {
  /* The band is positioned and the centre column was not, so the bars painted
     over the headline, the subhead and the CTA whenever the two met. Raised
     into the same layer the call cards already occupy, one step below them,
     so the text can never be crossed even if a future string grows the column.
     Verified against .card-complete at 1920/1440/1280/1024/900/768/360: the
     two boxes never intersect, so this changes no other paint relationship. */
  position: relative;
  /* z-index is set with the rest of the stacking order near the top of this
     file, where the canvas it has to beat is declared. */
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: var(--hero-centre-w);
  container-type: inline-size;
}
.hero-eyebrow {
  color: var(--color-sand);   /* the gradient's core is Ink Elevated: Ink Mist measures 4.48:1 here */
  margin-bottom: 12px;
}
/* THE HERO HEADLINE IS SIZED FROM ITS OWN COLUMN, and this is a departure
   from the system's stated 56-92px fluid range with a measured reason.

   The system assumes a hero whose headline has the row to itself. This one
   does not: ruling AN(c) gives the copy a left column and the object the
   right, and ruling AS pins that column at 345px -- the width of the word
   "operasyonlar" at 56px, which is the point below which the headline stops
   wrapping and starts overflowing into the object.

   So 56px is not the bottom of the range here, it is the exact size the
   column holds. Sizing the headline at the system's 92px maximum would set
   that word 567px wide in a 345px column. The headline therefore scales WITH
   its column, at the ratio the longest word fixes: 56/345 = 0.162. At 1425
   the column is 345px and the headline is 56px; at 1905 it is 457px and 74px;
   a 568px column would reach the system's 92px cap and stop there. The range
   is honoured at both ends, and it is the column rather than the viewport
   that decides where in the range this page sits.

   Turkish narrows on the width axis before it wraps -- see tokens.css -- so
   it fits inside the same ratio with room to spare rather than needing its
   own. */
.hero h1 {
  /* The owner sets the line break by hand (a newline in the string, ruling
     AX's owner); pre-line honours it and still wraps where the column is
     narrower than a line. */
  white-space: pre-line;
  /* Sized from the VIEWPORT again, and the ratio is the one the column gave.
     The column-times-0.162 rule existed because the column was pinned at the
     width of the headline's longest word, so the column was the honest
     measure of how big the type could be. The column is now 0.393W and the
     longest word no longer touches its edge, so that rule would jump the
     headline from 56px to 92px at 1440 -- three lines of display type where
     there were four of text. The owner drew the wider column against the
     headline AS IT IS. 3.89vw is 0.24 x 0.162: the same pixels at every width
     the old rule produced, now written without the column in them. */
  font-size: clamp(56px, 3.89vw, 92px);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  color: var(--color-linen);
  max-width: var(--headline-max-width);
}
.hero-sub {
  /* The lead paragraph. Inter 400 at 20px and NEVER 500: the system is
     explicit about it, and a bolded lead on this dark surface reads as a
     second headline competing with the real one. */
  font-size: var(--text-subheading);
  line-height: var(--leading-body);
  font-weight: var(--weight-regular);
  color: var(--color-sand);   /* the gradient's core is Ink Elevated, where Ink Mist measures 3.89:1 */
  max-width: var(--measure);
  margin: 20px 0 0;
  /* Justified, both edges flush, as in Word (owner, 2026-09-06). Turkish
     hyphenation is left on so a long compound is broken rather than the
     spaces stretched to hold it; the last line stays ragged, as Word's does. */
  text-align: justify;
  text-justify: inter-word;
  hyphens: auto;
  text-align-last: left;
}
.hero-cta { margin-top: 32px; }

/* The external-link glyph inside a booking CTA. Line drawn at 1.25px on a 20px
   grid per the Imagery rule. currentColor is the CTA's own Ink label, 5.48:1 on
   Ember, which clears the 3:1 non-text floor. It is chrome ON an existing Ember
   element, not a new Ember element type, so the budget of three is untouched.
   The label is wrapped in its own span because locale.js sets textContent on
   [data-i18n] and would delete this node on every language switch. */
.ext-glyph {
  width: 14px;
  height: 14px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The booking disclosure. The visitor leaves the origin and types a name and an
   e-mail into a third party, and until now the page never said so -- while an
   entire layer of it argues that data stays inside the customer's walls.
   Inter, not the machine face: this is a sentence a human wrote for a human.
   Centred on dark and left aligned on light, per the band rule. */
.cta-note {
  margin: var(--spacing-12) auto 0;
  max-width: 46ch;
  font-family: var(--font-body);
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-caption);
  color: var(--color-ink-mist);
}
/* Ruling AH: the hero canvas is a radial gradient whose core is Ink Elevated,
   where Ink Mist measures 3.89:1 and fails. Sand is 8.47:1 against that core. */
.hero-cta .cta-note { color: var(--color-sand); }
/* Ruling T: Ink Mist is 3.12:1 on Linen, so the light register takes Ink Slate
   at 6.52:1. Left aligned, because the light bands are. */
.booking-linkout .cta-note { margin-inline: 0; color: var(--color-ink-slate); }

/* ---- Waveform ---- */
.waveform-band {
  position: absolute;
  inset: auto 0 0 0;
  height: var(--wave-h);
  pointer-events: none;
}
.waveform {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  height: 100%;
  width: 100%;
  gap: 3px;
  -webkit-mask-image: linear-gradient(180deg, rgb(0 0 0) 0%, rgb(0 0 0) 60%, transparent 100%);
          mask-image: linear-gradient(180deg, rgb(0 0 0) 0%, rgb(0 0 0) 60%, transparent 100%);
}
.waveform-bar {
  flex: 1 1 0;
  max-width: 10px;
  height: calc(100% * var(--bar-amp, 1));
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

/* ---- Live call cards ----
   Desktop: an absolute overlay across the hero zone, cards at the edges.
   Below 1180: a normal band that follows the hero, so the fold keeps
   the waveform and the live card becomes the first scroll reward. */
/* THE CARDS YIELDED THE HERO, 2026-08-28. They were two absolute overlays at
   the hero's extremes, and with the brain arriving the hero would have carried
   four objects. They are now a band directly under the hero: the first scroll
   reward, completed call then live call, in the order the work happens.
   This also retires the three-column diagonal and its --hero-drop taper, which
   existed only to keep four objects from colliding. Fewer objects, no taper. */
.hero-cards {
  /* transparent for the same reason as .band-dark: this was Ink over Ink */
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: var(--spacing-32);
  padding: var(--spacing-64) var(--gutter);

}
.call-card {
  position: static;
  box-sizing: border-box;   /* 340px is the spec's rendered width, not its content box */
  width: var(--card-w, 340px);
  background: var(--color-ink-elevated);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-md);
  padding: var(--card-padding);
  text-align: left;
  pointer-events: auto;
}

/* Three columns from 1024 up. The card column narrows as the viewport does,
   so the centre never starves; the headline follows the centre's own width
   via cqw and therefore holds ~20ch at every one of these widths. */
/* THE TWO COLUMN HERO. Ruling AN(c): the text takes the left column and the
   brain owns the right, so nothing is drawn behind the headline and the text
   mask has almost nothing left to suppress.

   The column is sized from --brain-left-px, which js/brain.js writes on every
   resize from the object's REST position -- the right-hand one it holds while
   the copy is on screen, never the travelling one, so the column is a constant
   and cannot reflow under the reader mid-scroll.

   The query starts at 1180, NOT 1100, and it has to match the object's own
   threshold exactly. Between the two there is no object, so a left-aligned
   column would be text hugging the left of the page with half the row empty
   beside it and nothing in it. Ruling AR(e) moved both together.

   The fallback matters. If the object is disabled, still loading, or the
   browser never runs the script, --brain-left-px is unset and 44vw is used,
   which is inside the measured envelope at every width where this applies. */
@media (min-width: 1180px) {
  .hero-centre {
    /* align-self, NOT align-items on .hero: .waveform-band is a sibling in the
       same column flex and must keep its full width. */
    align-self: flex-start;
    align-items: flex-start;
    text-align: left;
    /* The column is published directly now, not derived here from the object's
       left edge. The arithmetic used to live in both files and had to agree;
       js/brain.js owns it. Ruling AS(b). */
    max-width: var(--hero-col-px, 44vw);
  }
  /* The headline and subhead were capped against a CENTRED column. The column
     is now the cap, so their own caps would only fight it. */
  .hero h1 { max-width: none; }
  .hero-sub { max-width: none; }
}

@media (min-width: 1180px) {
  /* The centre column is no longer starved by two 340px cards, so it takes the
     full 1200px column and the headline reaches its documented step without a
     container query fighting for it. The type scale is the authority, ruling AA,
     and the 22ch cap holds the measure. */
  .hero-zone { --hero-centre-w: 100%; }
  /* sized from the column, not the viewport: see .hero h1 above */
}

/* The card column, wherever the object is drawn. Ruling AR(d).

   The cards STACK rather than sitting side by side, and that is forced by
   arithmetic rather than chosen: the row is 340 + 32 + 340 = 712px, the object
   is 768px wide at 1425, and 712 + 768 + the margins between them is 1552
   against a 1425px viewport. There is no scroll offset at which a row and the
   object are both inside the band and clear of each other. A column is 340px
   and fits beside the object with room to spare.

   The lead is the empty flow above them. It is what makes the swap possible at
   all: the object crosses right-to-left and the cards end up right, so the two
   must pass each other, and no horizontal arrangement can avoid that. They are
   separated in time instead -- the cards stay below the object's band until it
   has arrived. js/brain.js solves the exact figure. */
@media (min-width: 1180px) {
  .hero-cards {
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: var(--spacing-32);
    padding-top: calc(var(--spacing-64) + var(--cards-lead-px, 0px));
    padding-left: var(--brain-cards-left-px, 50%);
    padding-right: var(--gutter);
    /* THE TAIL, solved like the lead: the band below must not rise under the
       object's layer names while they are up. js/brain.js solveLabelsAndTail()
       writes exactly the flow that takes, and no more. */
    padding-bottom: calc(var(--spacing-64) + var(--cards-tail-px, 0px));
    background: none;
  }
  .call-card { width: var(--card-w, 340px); max-width: none; }
}

.call-card-header {
  display: flex;
  align-items: center;
  gap: 8px;
}
.call-card-label { color: var(--color-sand); }
.call-card-timer {
  margin-left: auto;
  color: var(--color-sand);   /* ruling T: Ink Mist is 3.89:1 on Ink Elevated */
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  line-height: var(--leading-micro);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-micro);
  font-variant-numeric: tabular-nums;
}
.call-card-body { margin-top: 16px; display: flex; flex-direction: column; gap: 10px; }

.transcript-line {
  display: flex;
  gap: 8px;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-lg);
  letter-spacing: var(--tracking-body-sm);
}
.transcript-line .rule {
  flex: none;
  width: 2px; height: 12px;
  margin-top: 5px;
}
.transcript-line.from-customer { color: var(--color-ink-mist); }
.transcript-line.from-customer .rule { background: var(--color-ink-line); }
.transcript-line.from-agent { color: var(--color-linen); }
.transcript-line.from-agent .rule { background: var(--color-linen); }   /* ruling AB: was Ember */

.call-card-footer { margin-top: 16px; }

/* Ruling AE: a pill on the Live Call Card sits on Ink Elevated, so it takes an
   Ink fill exactly as ruling U requires of every other pill on that surface.
   That surface step is what buys the working label its 5.48:1; on the pill's
   own Ink Elevated fill the same Ember measured 4.44:1 and failed AA, and the
   build had been quietly painting it Sand under a rule written about Ink Mist. */
.call-card .status-pill { background: var(--color-ink); }

/* ---- Status pill ---- */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--color-ink-elevated);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  min-height: 22px;
}
.status-pill .pill-dot {
  width: 8px; height: 8px;
  border-radius: var(--radius-dot);
  background: var(--color-ink-mist);   /* the queued default; states override */
  flex: none;
}
.status-pill .pill-label {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  line-height: var(--leading-micro);
  letter-spacing: var(--tracking-micro);
  font-weight: var(--weight-medium);
  color: var(--color-ink-mist);        /* the queued default; states override */
  transition: color var(--dur-instant) linear;
}
.status-pill[data-state="working"]  .pill-dot   { background: var(--color-ember); }
.status-pill[data-state="working"]  .pill-label { color: var(--color-ember); }
.status-pill[data-state="complete"] .pill-dot   { background: var(--color-sand); }
.status-pill[data-state="complete"] .pill-label { color: var(--color-sand); }

/* ---- Responsive ---- */
@media (max-width: 1179.98px) {
  .hero-cards {
    /* relative, not static: static drops the z-index 3 set at the top of the
       file, and under ruling AY the object is drawn here -- with the band
       static the wireframe painted OVER the call card (MEASURED at 375x812,
       p 0.6). Relative flows exactly as static does. */
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-32);
    padding: 48px var(--gutter);
    /* Was an opaque Ink. Ruling AY draws the object behind this band on the
       phone; Ink over Ink otherwise, so nothing else changes. */
    background: none;
  }
  .call-card {
    position: static;
    width: min(340px, 100%);
  }
}
@media (max-width: 900px) {
  .nav-links { display: none; }
}
@media (max-width: 768px) {
  .hero-zone { --wave-h: 120px; }
}
@media (max-width: 480px) {
  /* Ruling P, delivered rather than merely intended: the bars give up the fold
     to the proof. The band hangs at the foot of the whole hero zone so the
     call card lands immediately under the CTA, which is the arrangement the
     ruling reversed the original fold trade to get. */
  .hero-zone { position: relative; padding-bottom: 96px; }
  /* .hero is the nearest positioned ancestor at wider widths, which would pin
     the band to the hero's own foot rather than the zone's, putting it back
     above the card. The zone is the containing block here. */
  .hero { position: static; }
  /* Deviation from elia-design.md's collapse list, documented in progress.html:
     the wordmark stays at every width. An unnamed cream circle is a worse
     failure than a fourth nav item; elia-design.md should gain the wordmark here. */
  /* Ruling D removed the compact nav CTA, so the full-size button now has to
     be paid for out of the nav's own spacing rather than the button's. */
  .nav { padding: 20px 16px; }
  /* Fold trade REVERSED 2026-08-25. The intro spends its whole budget
     promising that a call arrives, so the phone hero must actually carry one.
     The hero grows to hold it: the waveform gives up the fold, not the proof. */
  /* overflow-x: clip contains the full-bleed band when a scrollbar makes
     the client area narrower than the viewport; overflow-y stays visible. */
  .hero { min-height: 0; overflow-x: clip; overflow-y: visible; padding-bottom: 8px; }
  /* RULING P, delivered rather than intended. The band used to sit between the
     CTA and the call card in flow order, so the proof was below the fold at
     every phone height and the bars never gave it up. It now hangs at the foot
     of the whole hero zone: the card follows the CTA directly, and the bars
     take the overflow.
     Absolute against .hero-zone, which carries no horizontal padding, so the
     full bleed comes for free where the old static rule needed a negative
     margin to cancel the hero's own gutter. */
  .waveform-band {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    width: auto;
    margin: 0;
  }
  .hero-cards { padding-top: 20px; padding-bottom: 56px; }
  .nav-left { gap: 8px; }
  .nav-right { gap: 12px; }
  .hero-zone { --wave-h: 96px; }

  .call-card { width: 100%; max-width: 340px; }
}

/* ---- Piece B: light register, product core ---- */
.band-light {
  background: var(--color-linen);
  color: var(--color-ink);
  padding: var(--spacing-96) var(--gutter);
}
.band-inner { max-width: var(--page-max-width); margin: 0 auto; }
.band-eyebrow { color: var(--color-ink-slate); margin: 0 0 12px; }
.band-light h2 {
  font-size: var(--text-heading);
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  font-weight: var(--weight-regular);
  color: var(--color-ink);
  max-width: var(--headline-max-width);
}
.band-body {
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--color-ink-slate);
  max-width: 62ch;
  margin: 20px 0 0;
}

/* Application window frame, not browser chrome */
.product-surface {
  margin-top: var(--spacing-48);
  background: var(--color-linen);
  border: 1px solid var(--color-linen-line);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.surface-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 36px;
  padding: 0 16px;
  background: var(--color-linen-sunken);
  border-bottom: 1px solid var(--color-linen-line);
}
.surface-title { color: var(--color-ink-slate); }
.surface-body { display: flex; min-height: 380px; }

/* The 200px destination rail is DELETED, 2026-08-28. Five destinations --
   Çağrılar, Kayıtlar, Randevular, Raporlar, Ayarlar -- assert a second system
   the buyer must adopt and learn, directly beneath copy promising the record
   waits in the ERP they already run. It was the largest object on the light
   register arguing against the positioning the band exists to make. The frame
   is now the CUSTOMER's record, and Elia appears in it as provenance on the
   rows it wrote, which is the whole claim in one element. */
/* Provenance. Mono, because ELIA in this row is a system name, which is what
   the machine face is for; it is the same register as the LOGO TIGER 3 label
   at the other end of the row. No new colour: Ink Slate is the light
   register's body colour at 6.52:1. */
.write-by {
  flex: none;
  color: var(--color-ink-slate);
}
.band-light[id] { scroll-margin-top: 96px; }

.surface-main { flex: 1; padding: 20px; min-width: 0; }
.call-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body-sm);
}
.call-table th {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  line-height: var(--leading-micro);
  letter-spacing: var(--tracking-micro);
  font-weight: var(--weight-medium);
  color: var(--color-ink-slate);
  text-align: left;
  background: var(--color-linen-sunken);
  padding: 8px 12px;
}
.call-table td {
  padding: 6px 12px;
}
/* Ruling G: the mono law outranks the component's "cell text Inter" line.
   Timestamps and plates are machine metadata; KONU stays the human face. */
.call-table td:nth-child(1), .call-table td:nth-child(2) {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  line-height: var(--leading-micro);
  letter-spacing: var(--tracking-micro);
  font-weight: var(--weight-medium);
  color: var(--color-ink-slate);
  white-space: nowrap;
}
.call-table td {
  border-bottom: 1px solid var(--color-linen-line);
  color: var(--color-ink);
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}
.call-table td.ref {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  line-height: var(--leading-micro);
  letter-spacing: var(--tracking-micro);
  font-weight: var(--weight-medium);
  color: var(--color-ink-slate);
}

/* Status pills on the light register */
.status-pill.pill-light {
  background: var(--color-linen-sunken);
  border-color: var(--color-linen-line);
}
/* Ruling T: a light-register pill with no state fell through to the dark
   register default, putting Ink Mist on Linen Sunken at 2.90:1. */
.status-pill.pill-light .pill-dot   { background: var(--color-ink-slate); }
.status-pill.pill-light .pill-label { color: var(--color-ink-slate); }
.status-pill.pill-light[data-state="working"]  .pill-dot   { background: var(--color-ember); }
.status-pill.pill-light[data-state="working"]  .pill-label { color: var(--color-ink); }
.status-pill.pill-light[data-state="complete"] .pill-dot   { background: var(--color-ink-slate); }
.status-pill.pill-light[data-state="complete"] .pill-label { color: var(--color-ink-slate); }
.status-pill.pill-light[data-state="queued"]   .pill-dot   { background: var(--color-ink-slate); }   /* ruling T */
.status-pill.pill-light[data-state="queued"]   .pill-label { color: var(--color-ink-slate); }   /* ruling T */

/* Record write rows: the commit moment */
.writes-title { color: var(--color-ink-slate); margin: 24px 0 8px; }
.write-rows { display: flex; flex-direction: column; gap: 8px; }
.write-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  box-sizing: border-box;
  height: 44px;
  padding: 0 16px;
  background: var(--color-linen-sunken);
  border: 1px solid var(--color-linen-line);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.write-system { color: var(--color-ink-slate); flex: none; }
.write-field { font-size: var(--text-body-sm); letter-spacing: var(--tracking-body-sm); color: var(--color-ink); flex: 1; min-width: 0; }
.write-ref {
  color: var(--color-ink-slate);
  background: var(--color-linen);
  border: 1px solid var(--color-linen-line);
  border-radius: var(--radius-sm);
  padding: 3px 6px;
}
/* Reserved, not hidden. Collapsed until the reference arrived, the row grew
   at the exact moment of the commit -- the one event bar.md calls the most
   satisfying on the page, landing as a jump. */
.write-ref:empty { visibility: hidden; }
.write-ref:empty::after { content: "SRV-00000"; }
.write-sweep {
  position: absolute;
  inset: 0 auto 0 0;
  width: 40%;
  background: linear-gradient(90deg, transparent, rgb(255 90 54 / 0.18), transparent);
  transform: translateX(-100%);
  pointer-events: none;
}
.write-row.committing .write-sweep {
  animation: record-write-sweep var(--dur-sweep) var(--ease-signal) 1 both;
}

/* Activity feed */
.surface-feed {
  width: 280px;
  box-sizing: border-box;
  flex: none;
  border-left: 1px solid var(--color-linen-line);
  padding: 20px 16px;
}
.feed-title { color: var(--color-ink-slate); margin: 0 0 12px; }
.feed-item {
  display: flex;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-linen-line);
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-caption);
  color: var(--color-ink-slate);
}
.feed-item .mono { color: var(--color-ink-slate); flex: none; }

@media (max-width: 1024px) {
  .surface-feed { display: none; }
}
@media (max-width: 768px) {
  .band-light { padding: var(--spacing-64) var(--gutter); }
}
/* At phone width the table restacks as cards: plate and belge share the
   top line, topic below, full status pill last. Nothing clips, the
   call-to-record join stays visible, SAAT alone yields. */
@media (max-width: 540px) {
  .call-table, .call-table tbody { display: block; }
  .call-table thead { display: none; }
  .call-table tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--color-linen-line);
  }
  .call-table td { display: block; border-bottom: none; padding: 0; height: auto; }
  .call-table td:nth-child(1) { display: none; }
  .call-table td:nth-child(2) { order: 1; }
  .call-table td:nth-child(5) { order: 2; margin-left: auto; }
  .call-table td:nth-child(3) { order: 3; flex-basis: 100%; }
  .call-table td:nth-child(4) { order: 4; }
  .write-row { gap: 10px; flex-wrap: wrap; height: auto; min-height: 44px; padding: 10px 16px; }
  .write-system { order: 1; }
  /* Shares the system name's order so it keeps DOM position beside it; without
     an order it would default to 0 and jump ahead of everything. */
  .write-by { order: 1; }
  .write-ref { order: 2; margin-left: auto; }
  .write-field { order: 3; flex-basis: 100%; }
}

/* ---- Piece C: seams, how it works, integrations ---- */

/* The register seam: navy meets cream through dawn, never through mud. */
.register-seam {
  height: 120px;
  background: linear-gradient(180deg,
    var(--color-ink) 0%,
    color-mix(in oklab, var(--color-sand) 26%, var(--color-ink)) 55%,
    var(--color-linen) 100%);
}
.register-seam.reverse {
  background: linear-gradient(180deg,
    var(--color-linen) 0%,
    color-mix(in oklab, var(--color-sand) 26%, var(--color-ink)) 45%,
    var(--color-ink) 100%);
}

/* Dark band: centred, per the band model. */
.band-dark {
  /* No background. It used to be var(--color-ink), which is the SAME colour the
     body already paints, so the fill was invisible and cost nothing to look at.
     It cost the field everything: the canvas sits at z-index 0 and main at 1, so
     an opaque band hid the field completely below the hero. Measured, the field
     was invisible at every scroll position past the hero, which meant the three
     baked orientations never turned anywhere a reader could see them.
     The LIGHT bands stay opaque. They are a different register by design and
     ruling AK already records that the field is covered on Linen. */
  color: var(--color-linen);
  padding: var(--spacing-96) var(--gutter);
}
.band-dark[id] { scroll-margin-top: 96px; }
.band-centred {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.eyebrow-dark { color: var(--color-ink-mist); }
.band-dark h2 {
  font-size: var(--text-heading-lg);
  line-height: var(--leading-heading-lg);
  letter-spacing: var(--tracking-heading-lg);
  font-weight: var(--weight-light);
  color: var(--color-linen);
  max-width: var(--headline-max-width);
}
.body-dark { color: var(--color-ink-mist); }

/* ================= The solutions orbit =================
   Ruling BA (owner, 2026-09-18): five products of Elia Workforce on one ring,
   72 degrees apart, in the manner of the owner's reference -- hairline
   circles on dashed orbits over a constellation -- in this page's own
   palette. It replaces the stack band; what that band said about each
   product is on the product's own page.

   ONE LAYOUT AT EVERY WIDTH. The diagram is a square sized from its column
   and everything inside it is a fraction of that square: the ring's radius is
   34%, a node's diameter 27%, so two neighbours stand 0.34 x 2 sin 36deg =
   40% apart centre to centre and 13% clear of each other, at 343px as at
   860. Left and top percentages are both of the same square, which is what
   lets five fixed (cos, sin) pairs place the pentagon without a script.
   Type is sized in cqw off the same square, with a px fallback first. */
/* THE REVEAL, ruling BH. The band is taller than the frame and its content
   sticks, so the reader scrolls through it while the picture holds. The
   extra height is the reveal's whole clock (js/main.js); ORBIT_TRAVEL is
   how much scroll the five take -- 5 x 28vh, about a screen and a half.
   Only under html.orbit-scrub, which the script sets and reduced motion
   never gets: without it the band is its natural height, nothing is dim.
   The orbit is capped by the frame's height as well as its column, so the
   heading, the hint and the whole ring fit the pinned frame at once. */
.orbit-band { --orbit-travel: 140vh; }
html.orbit-scrub .orbit-band { min-height: calc(100vh + var(--orbit-travel)); padding-top: 0; padding-bottom: 0; }
html.orbit-scrub .orbit-pin {
  position: sticky;
  top: 0;
  min-height: 100vh;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  /* No side padding of its own: the band already pads by the gutter, and
     the pair cost the phone's orbit 48px (279 against 327, MEASURED). */
  padding: calc(91px + var(--spacing-24)) 0 var(--spacing-32);
}
html.orbit-scrub .orbit-pin > .band-inner { width: 100%; }
html.orbit-scrub .orbit-field { margin-top: var(--spacing-24); }
html.orbit-scrub .orbit-band h2 { max-width: 36ch; }
html.orbit-scrub .orbit { width: min(100%, 860px, max(300px, calc(100vh - 390px))); }
@media (max-width: 768px) { html.orbit-scrub .orbit { width: min(100%, max(300px, calc(100vh - 290px))); } }
/* A short frame -- the zoomed-in browser, a phone on its side -- keeps the
   reveal and loses what it cannot hold: the hint, most of the head's air. */
@media (max-height: 640px) {
  html.orbit-scrub .orbit-pin { padding-top: calc(91px + var(--spacing-8)); padding-bottom: var(--spacing-16); }
  html.orbit-scrub .orbit-hint { display: none; }
  html.orbit-scrub .orbit-band h2 { font-size: clamp(24px, 4vh, 36px); }
  html.orbit-scrub .orbit-field { margin-top: var(--spacing-12); }
  html.orbit-scrub .orbit { width: min(100%, max(280px, calc(100vh - 190px))); }
}
/* The smallest ring: tighter nodes so two-line names never cross. */
@container (max-width: 339.98px) {
  .orbit-node { padding: 5%; gap: 3px; }
  .orbit-disc { width: 26px; height: 26px; }
  .orbit-name { font-size: 10px; line-height: 1.1; }
  .orbit-hub img { width: 30px; }
}

/* THE PHONE (ruling BL). Below 1180 the heading and the hint flow above, the
   brain with the five names round it follows them, and the RING alone is
   what sticks: the frame it needs is its own height plus the nav. The pin
   wrapper stops pinning; the field does it instead. */
.orbit-mind { display: none; }
@media (max-width: 1179.98px) {
  html.orbit-scrub .orbit-pin { position: static; min-height: 0; display: block; padding: var(--spacing-96) 0 0; }
  html.orbit-scrub .orbit-hint { display: block; }
  html.orbit-scrub .orbit-band h2 { font-size: var(--text-heading-lg); }
  .orbit-mind {
    position: relative;
    display: block;
    width: min(100%, 420px);
    aspect-ratio: 1;
    margin: var(--spacing-32) auto 0;
  }
  .orbit-mind-canvas { position: absolute; inset: 12% 12%; width: 76%; height: 76%; display: block; touch-action: pan-y; }
  .orbit-mind-name {
    position: absolute;
    font-size: 15px;
    line-height: 1.2;
    color: var(--color-sand);
    white-space: nowrap;
  }
  .orbit-mind-name.is-1 { right: 4%; top: 0; }
  .orbit-mind-name.is-2 { left: 4%; top: 2%; }
  .orbit-mind-name.is-3 { left: 0; top: 44%; }
  .orbit-mind-name.is-4 { right: 0; top: 56%; }
  .orbit-mind-name.is-5 { left: 8%; bottom: 0; }
  /* The band's own height is its content; the STAGE round the field is what
     carries the ring's scroll, so the sticky field has a range to stick
     through (a sticky box only travels inside its parent -- the first cut
     gave it a parent no taller than itself, and it never stuck). The ring
     sits at the top of the frame, under the nav, so the brain above and the
     ring are a short scroll apart. */
  html.orbit-scrub .orbit-band { min-height: 0; }
  /* width 100%: the stage is an item of the centred column flex, and left
     to its content it was 0 wide, with the ring's percentage width inside it
     (MEASURED: field 0, ring 0). */
  html.orbit-scrub .orbit-stage { display: block; width: 100%; min-height: calc(100vh + var(--orbit-travel)); margin-top: var(--spacing-24); }
  html.orbit-scrub .orbit-field {
    position: sticky;
    top: 0;
    height: 100vh;
    box-sizing: border-box;
    display: flex;
    /* Centred (owner, ruling BN): the ring holds with the mark at the exact
       middle of the screen, and the frame is one screen, no more. */
    align-items: center;
    justify-content: center;
    padding: 0;
    margin-top: 0;
  }
  html.orbit-scrub .orbit { width: min(100%, max(300px, calc(100vh - 220px))); }
  /* The link cue stays on the small ring: the owner wants every circle to
     say it opens a page. */
  .orbit-cta { display: inline-flex; font-size: 9px; margin-top: 0; }
}

/* The arc on the ring: Sand, drawn to p, from the top, clockwise. */
.orbit-rings .orbit-sweep {
  fill: none;
  stroke: var(--color-sand);
  stroke-opacity: 0.9;
  stroke-width: 1.5;
  stroke-dasharray: none;
  stroke-linecap: round;
}
html:not(.orbit-scrub) .orbit-sweep { display: none; }

/* The circles asleep: dim and a touch small. --wake (0..1) brings each up;
   awake, a circle keeps a Sand edge and shows its İncele line -- the
   affordance the first-time readers were missing. */
html.orbit-scrub .orbit-at { opacity: calc(0.22 + 0.78 * var(--wake, 0)); }
html.orbit-scrub .orbit-node {
  transform: scale(calc(0.86 + 0.14 * var(--wake, 0)));
  border-color: color-mix(in srgb, var(--color-sand) calc(var(--wake, 0) * 70%), var(--color-ink-line));
  box-shadow: 0 0 0 calc(var(--wake, 0) * 10px) color-mix(in srgb, var(--color-sand) 10%, transparent);
}
html.orbit-scrub .orbit-at.is-awake .orbit-node { box-shadow: 0 0 0 0 transparent; transition: box-shadow var(--dur-slow) var(--ease-settle); }
.orbit-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
  font-size: 11px;
  font-size: clamp(10px, 1.6cqw, 13px);
  color: var(--color-sand);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-signal);
}
.orbit-cta::after { content: "\2192"; }
.orbit-at.is-awake .orbit-cta, html:not(.orbit-scrub) .orbit-cta { opacity: 1; }
@media (hover: hover) { .orbit-node:hover .orbit-cta { opacity: 1; } }
@container (max-width: 459.98px) { .orbit-cta { font-size: 9px; margin-top: 0; } }

.orbit-hint {
  margin: var(--spacing-16) 0 0;
  /* Wider (owner, 2026-09-29): the new hint is four sentences, and at 52ch
     it took five lines and pushed the ring off the pinned frame. */
  max-width: 78ch;
  color: var(--color-ink-mist);
}
.orbit-field {
  position: relative;
  width: 100%;
  max-width: var(--page-max-width);
  margin-top: var(--spacing-40);
  display: flex;
  justify-content: center;
}
.orbit-sky {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  /* The field is cropped from a wider sky; it fades out rather than ending
     on a cut line. */
  -webkit-mask-image: radial-gradient(ellipse 60% 62% at 50% 50%, #000 62%, transparent 100%);
          mask-image: radial-gradient(ellipse 60% 62% at 50% 50%, #000 62%, transparent 100%);
}
.sky-lines line { stroke: var(--color-ink-line); stroke-width: 1; vector-effect: non-scaling-stroke; }
.sky-dots circle { fill: var(--color-sand); opacity: 0.7; }
.sky-dots circle.is-far { fill: var(--color-ink-mist); opacity: 0.55; }

.orbit {
  position: relative;
  container-type: inline-size;
  width: min(100%, 860px);
  aspect-ratio: 1;
}
.orbit-rings {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.orbit-rings circle {
  fill: none;
  stroke: var(--color-ink-mist);
  stroke-opacity: 0.45;
  stroke-width: 1;
  stroke-dasharray: 3 7;
  vector-effect: non-scaling-stroke;
}
.orbit-rings .orbit-ring-hub { stroke-dasharray: none; stroke: var(--color-ink-line); stroke-opacity: 1; }
/* The orbits drift, once round in four minutes: slow enough to be noticed
   only by someone looking for it. It is decoration on decoration -- nothing a
   reader reads moves -- and it stops under reduced motion. */
.orbit-rings-spin { transform-origin: 500px 500px; animation: orbit-drift 240s linear infinite; }
@keyframes orbit-drift { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .orbit-rings-spin { animation: none; } }

.orbit-hub {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  gap: 1.4cqw;
  color: var(--color-sand);
  white-space: nowrap;
}
.orbit-hub img { width: 56px; width: clamp(34px, 9cqw, 76px); height: auto; border-radius: var(--radius-sm); }
.orbit-hub .mono { font-size: 11px; font-size: clamp(10px, 1.5cqw, 13px); }

.orbit-nodes { list-style: none; margin: 0; padding: 0; }
.orbit-at {
  position: absolute;
  width: 27%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
}
/* -90deg, then +72 each, clockwise: (cos, sin) x 34%. */
.orbit-at-1 { left: 50%;                        top: calc(50% - 34%); }
.orbit-at-2 { left: calc(50% + 34% * 0.9511);   top: calc(50% - 34% * 0.3090); }
.orbit-at-3 { left: calc(50% + 34% * 0.5878);   top: calc(50% + 34% * 0.8090); }
.orbit-at-4 { left: calc(50% - 34% * 0.5878);   top: calc(50% + 34% * 0.8090); }
.orbit-at-5 { left: calc(50% - 34% * 0.9511);   top: calc(50% - 34% * 0.3090); }

.orbit-node {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  gap: 1.3cqw;
  padding: 8%;
  border-radius: 50%;
  border: 1px solid var(--color-ink-line);
  background: var(--color-ink);
  color: var(--color-linen);
  text-decoration: none;
  text-align: center;
  transition: border-color var(--dur-base) var(--ease-signal),
              background-color var(--dur-base) var(--ease-signal),
              transform var(--dur-base) var(--ease-settle);
}
.orbit-disc {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  width: clamp(32px, 8.4cqw, 72px); height: clamp(32px, 8.4cqw, 72px);
  border-radius: 50%;
  background: var(--color-linen);
  color: var(--color-ink);
  transition: transform var(--dur-base) var(--ease-settle);
}
.orbit-disc svg { width: 54%; height: 54%; }
.orbit-name {
  font-family: var(--font-display);
  font-weight: var(--weight-semi);
  font-size: 14px;
  font-size: clamp(11px, 2.5cqw, 21px);
  line-height: 1.15;
  letter-spacing: 0.005em;
  white-space: nowrap;
}
.orbit-role {
  display: none;
  max-width: 78%;
  font-size: 13px;
  line-height: 1.3;
  /* Two lines reserved, so a one-line role does not sit its node's disc and
     name lower than its neighbours'. */
  min-height: 2.6em;
  color: var(--color-ink-mist);
}
/* The small square: the name takes two lines so the longest, Private AI and
   Knowledge, clear the circle's chord; the role line needs a node of 180px
   or more and joins above that. */
@container (max-width: 639.98px) { .orbit-name span { display: block; } }
@container (min-width: 700px)    { .orbit-role { display: block; } }
@container (max-width: 459.98px) { .orbit-hub .mono { display: none; } }
.orbit-stage { display: contents; }

@media (hover: hover) {
  .orbit-node:hover { border-color: var(--color-sand); background: var(--color-ink-elevated); }
  .orbit-node:hover .orbit-disc { transform: scale(1.06); }
  /* Ruling T: Ink Mist is 3.89:1 on Ink Elevated, so the role takes Sand
     with the surface. */
  .orbit-node:hover .orbit-role { color: var(--color-sand); }
}
.orbit-node:active { transform: scale(0.98); }
.orbit-node:focus-visible { outline: 2px solid var(--color-sand); outline-offset: 4px; }
@media (prefers-reduced-motion: reduce) {
  .orbit-node, .orbit-disc { transition: none; }
  .orbit-node:active, .orbit-node:hover .orbit-disc { transform: none; }
}

/* ================= The stack =================
   The Agent Roster Card is ABSORBED here, per ruling W: the job / schedule /
   system-of-record triple and the deployment label survive, the card frame
   does not.

   The enclosure is the dark-register sibling of the Light Product Surface,
   with its canvas one step BELOW the page per ruling AC, so the ladder runs
   page -> canvas down -> chrome up -> row up.

   THE SPINE, ruling AG. Five ordinals on one vertical line, one entry pitch apart:
   the pitch is SEEN rather than inferred. It has no hairline; see below. It also
   empties the eyebrow of everything but the product name, which had left
   every entry with two byte-identical mono lines. The rail's index is pinned,
   interactive and tracks the reader; this is a static rule that never
   changes. The opposition that matters is intact. */
.stack {
  /* One spine width and one inset, so the chrome, the ordinals, the entry
     text and the terminal line all measure from the same two numbers. */
  --stack-spine: 64px;
  --stack-inset: var(--spacing-24);
  box-sizing: border-box;
  width: 100%;
  max-width: var(--page-max-width);
  margin-top: var(--spacing-40);
  text-align: left;
  background: var(--color-ink-deep);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-md);
  overflow: hidden;
}
/* The chrome sits BETWEEN the canvas and the content, and the spine divides
   it, so the strip is a header with two cells rather than a mostly empty bar. */
.stack-head {
  display: grid;
  grid-template-columns: var(--stack-spine) minmax(0, 1fr);
  align-items: center;
  box-sizing: border-box;
  height: 36px;
  background: var(--color-ink);
  border-bottom: 1px solid var(--color-ink-line);
}
.stack-title { grid-column: 2; padding-left: var(--stack-inset); color: var(--color-sand); }
/* The closing rule spans the whole enclosure; only the TEXT is capped. */
.stack-foot {
  padding: var(--spacing-12) var(--stack-inset) var(--spacing-12) calc(var(--stack-spine) + var(--stack-inset));
  border-top: 1px solid var(--color-ink-line);
}
.stack-foot p {
  margin: 0;
  max-width: var(--content-max-width);
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-caption);
  color: var(--color-ink-mist);
}

/* ---- One layer entry ---- */
.layer {
  display: grid;
  grid-template-columns: var(--stack-spine) minmax(0, 452px) minmax(0, 1fr);
  column-gap: 0;
  align-items: start;
  box-sizing: border-box;
  min-height: 352px;   /* the tallest entry once the wells' interiors recessed */
  padding: var(--spacing-32) var(--stack-inset) var(--spacing-32) 0;
  border-top: 1px solid var(--color-ink-line);
}
/* first-child loses 1px of border, so it gains 1px of padding: without this
   the first interval measures 289 where the other four measure 288. */
.layer:first-child { border-top: 0; padding-top: calc(var(--spacing-32) + 1px); }
.layer-no {
  grid-column: 1;
  align-self: start;
  margin: 0;
  padding-left: var(--stack-inset);
  font-size: var(--text-mono-sm);
  line-height: var(--leading-mono-sm);
  margin-top: -5px;   /* optical: 13px and 11px mono share a box top but not a baseline */
  letter-spacing: var(--tracking-mono-sm);
  font-weight: var(--weight-regular);
  color: var(--color-sand);
}
/* THE SPINE HAS NO HAIRLINE, and that is a correction, not an omission. Drawn
   as a 1px Ink Line rule it measured 1.67:1 on this canvas: the least visible
   mark in the enclosure was the one carrying the pitch, which is exactly what
   ruling AG's second half forbids. It was also redundant twice over, because
   the ordinals and the entry separators already mark the interval between
   them, and it put a vertical line at the same x as the step rail's own track
   two hundred pixels below, which spent one of the four oppositions the Stack
   Enclosure spec calls load bearing. The ordinals alone hold the column. */
.stack-body { position: relative; }
/* STRETCHED, so the auto margin on the foot has free space to consume and
   every meta rule lands on one shared horizontal. Left as start-aligned, the
   auto margin was dead CSS and the five rules ragged by 26px. */
.layer-text { grid-column: 2; padding-left: var(--stack-inset); align-self: stretch; display: flex; flex-direction: column; align-items: flex-start; width: 100%; }
.layer-view { grid-column: 3; margin-left: var(--spacing-48); }
.layer-eyebrow {
  font-size: var(--text-mono-sm);
  line-height: var(--leading-mono-sm);
  letter-spacing: var(--tracking-mono-sm);
  font-weight: var(--weight-regular);
  color: var(--color-linen);
  margin: 0 0 var(--spacing-12);
}
.layer h3 {
  font-size: var(--text-subheading);
  line-height: var(--leading-subheading);
  letter-spacing: var(--tracking-subheading);
  font-weight: var(--weight-medium);
  color: var(--color-linen);
  max-width: 22ch;
  margin: 0;
}
.layer-body {
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--color-ink-mist);
  max-width: 40ch;
  margin: var(--spacing-12) 0 0;
}
/* A real tab stop. margin-left:auto IS space-between, and it opened holes of
   85 to 145px at desktop and 250 to 306 stacked, five entries and five values.
   A fixed right column also gives SAHADA and HAZIR one shared LEFT edge. */
.layer-foot {
  display: grid;
  /* 100px, not 88. The tab stop has to clear the LONGEST deployment label in
     EITHER language, and IN PRODUCTION measures 97.24px against SAHADA's 44.88.
     At 88 it wrapped to two lines and made the Voice entry's foot 16px taller
     than the other four -- the pitch the spine exists to make visible, broken
     by one word. One value for both locales, so the stop is shared across the
     five entries AND identical between languages. */
  grid-template-columns: minmax(0, 1fr) 100px;
  align-items: center;
  /* 8, not 16. The foot is capped at the body's own 40ch measure -- 404px --
     and the widest case across BOTH locales is Turkish YERİNDE ÇALIŞTIRMA at
     294.33px beside English IN PRODUCTION at 97.24px, which is 391.57px of
     content. Sixteen does not fit in the 12.43px left over; eight fits with
     4.43px to spare. Widening the cap was the alternative and it is worse: the
     foot rule would then overhang the body paragraph above it, which is the
     defect the 40ch cap was introduced to fix. Nine of the ten entry-and-locale
     combinations still show a 100px gap or more; this only binds the widest. */
  gap: var(--spacing-8);
  width: 100%;
  max-width: 40ch;
  margin-top: auto;
  padding-top: var(--spacing-16);
  border-top: 1px solid var(--color-ink-line);
}
/* nowrap so a future label that outgrows the column overflows VISIBLY rather
   than silently re-wrapping and changing one entry's height again. */
.layer-deploy { white-space: nowrap; }
.layer-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  color: var(--color-ink-mist);
  margin: 0;
  max-width: none;
}
.layer-meta .vrule,
.layer-meta span { white-space: nowrap; }
.layer-deploy { justify-self: start; color: var(--color-ink-mist); }
.layer-deploy.is-live { color: var(--color-sand); }

/* ---- The wells ----
   Every well a DIFFERENT SHAPE, tested on a screen rather than in a spec. */
/* The wells STRETCH and close on the same horizontal as the foot rule beside
   them. Left to their natural height they ended at five different places,
   ragging across 92px and leaving an average of 97px of canvas in the same
   bottom-right corner of every entry: a third of each cell, five times, in an
   L. Making the pitch visible is what made that hole visible. Only the left
   column was closing; now both do. */
.layer-view {
  display: flex;
  flex-direction: column;
  align-self: stretch;
  justify-content: flex-start;
  box-sizing: border-box;
  gap: var(--spacing-12);
  min-height: 176px;
  padding: var(--spacing-20);
  background: var(--color-ink-elevated);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-md);
}
/* Ruling T: on Ink Elevated, Ink Mist is 3.89:1 and takes Sand instead. */
.lv-call-meta, .qa-label, .qa-q, .source-label, .source-doc, .tl-sys, .inbound-label, .perimeter-edge {
  color: var(--color-sand);
}
/* Interiors recess INTO the panel, one step down, the way a console's rows do. */

/* 1. Voice. The metadata line is what makes the transcript visibly a
   conversation rather than two sentences above a record row. */
.lv-call-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  max-width: none;
}
/* The recess. Any block that is CONTENT rather than chrome sits one step into
   the panel. Written once: three wells were unbounded text on a surface, which
   is the panel change half-applied. */
.qa.is-well, .tl-stop.is-well, .lv-outcome {
  box-sizing: border-box;
  background: var(--color-ink);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
  padding: var(--spacing-12) var(--spacing-16);
}
/* The stretch lands HERE, once, above the block that is the well's
   consequence. Divided by space-between it became 39px between every pair in
   Voice and 44px in Agents -- holes three and five times the authored gap. */
.lv-voice > .lv-outcome,
.lv-agents > .act-row:last-child,
.lv-knowledge > .source { margin-top: auto; }
.lv-talk { display: flex; flex-direction: column; gap: var(--spacing-8); }
.lv-turn {
  display: flex;
  align-items: baseline;
  gap: var(--spacing-12);
  margin: 0;
  padding: 0;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-sand);
}
.lv-turn.is-agent { color: var(--color-linen); }
/* The speaker is named rather than ticked. A 2px mark is punctuation; a name is
   a participant, which is what separates a console from a mockup. */
.lv-who { flex: none; min-width: 56px; color: var(--color-sand); }
/* The record hangs off the agent's own rule as the consequence of what was
   just said, rather than standing as a fourth filled chip identical to the
   three in the Agents well two entries down. Same leading-rule device as the
   transcript above it, so it reads as the line's outcome. */
.lv-outcome {
  display: flex;
  align-items: baseline;
  gap: var(--spacing-12);
  margin: 0;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-linen);
}
.lv-outcome .mono { flex: none; color: var(--color-sand); }
.lv-outcome .lv-ref { margin-left: auto; }
.lv-outcome > span:nth-child(2) { flex: 1; min-width: 0; }

/* 2. Knowledge. Labelled on both sides, because SORU with no YANIT is half a
   transcript. The question takes Sand rather than Ink Mist so it cannot be
   confused with the marketing body 500px to its left, which is the same
   colour at the same size. The citation is INDENTED past the question: a
   quotation rule flush with what it quotes is a tick, not a citation mark. */
.lv-knowledge { gap: var(--spacing-20); }
.qa { display: flex; flex-direction: column; }
.qa.is-well { gap: 0; }
.qa-label { margin: 0 0 var(--spacing-8); }
.qa-label-a { margin-top: var(--spacing-16); }
.qa-q {
  margin: 0;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-sand);
  max-width: 46ch;
}
.qa-a {
  margin: 0;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-sand);
  max-width: 52ch;
}
.source { display: flex; align-items: stretch; gap: var(--spacing-12); margin-left: var(--spacing-24); }
.source-rule { flex: none; width: 2px; background: var(--color-sand); }
.source-body { display: flex; flex-direction: column; gap: var(--spacing-4); min-width: 0; }

/* Three values, not two. Set at the same size and colour as the question
   above it, the cited document was one voice with the thing it was citing. */
.source-doc {
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
}
/* The locator takes the peak: it is the part a reader can go and check.
   Linen at 16.31:1 against the title's Sand at 11.38:1, and the machine face,
   because a pointer into a document is machine metadata while the document's
   own title is not. Sentence case, per the Case rule at 13px. */
.source-loc {
  font-size: var(--text-mono-sm);
  line-height: var(--leading-mono-sm);
  letter-spacing: var(--tracking-mono-sm);
  font-weight: var(--weight-regular);
  color: var(--color-linen);
}

/* 3. Agents. Three DIFFERENT systems, and one shared left edge for the action
   text: as flex items the three system names set three different starts, in a
   well that is meant to read as a record. */
.lv-agents { gap: var(--spacing-8); }
.act-row {
  display: flex;
  align-items: center;
  gap: var(--spacing-16);
  box-sizing: border-box;
  min-height: 44px;              /* fixed, the two-line row rendered at zero padding */
  padding: 10px var(--spacing-16);
  background: var(--color-ink);      /* recessed INTO the panel; see the Layer Entry surface rule */
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-md);
}
.act-sys { color: var(--color-sand); flex: none; min-width: 140px; white-space: nowrap; }
.act-do {
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-linen);
  flex: 1;
  min-width: 0;
}
.act-ref {
  color: var(--color-sand);
  background: var(--color-ink-deep);   /* the row recessed to Ink; the tag steps again */
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
  padding: 3px 6px;
  flex: none;
}
/* Ruling U: a pill on an Ink Elevated surface takes an Ink fill, which is
   what buys the Ember label 5.48:1 instead of 4.44:1. */
.act-row .status-pill { background: var(--color-ink-deep); flex: none; }   /* ruling U, against the row's own Ink */
.status-pill[data-state="escalated"] { border-color: var(--color-ember); }
.status-pill[data-state="escalated"] .pill-dot { background: var(--color-ember); }
.status-pill[data-state="escalated"] .pill-label { color: var(--color-ember); }
/* Ruling X: nothing here moves, including a dormant transition on a pill
   whose state can never change. */
#katmanlar .pill-label { transition: none; }

/* 4. Workflow. TWO marks, ONE interval. Drawn with three marks the axis gave
   four days 278px and zero days 139px, which said two days passed between two
   events on the same day. Both day-five events now hang under one mark, so
   the only interval with elapsed time is the only interval with width.
   The run is Sand, not Ink Line: at 1.67:1 on this canvas a hairline is not a
   shape, and elia-design.md's own ruling says a claim carried by an invisible mark
   is carried by its caption. Ruling AG.
   The caption is a SIBLING of the run and sits ABOVE it, so the width is
   uninterrupted and the label survives the stacked breakpoint. */
.lv-flow > .tl { height: 100%; }
.tl {
  display: grid;
  grid-template-columns: 2px minmax(0, 1fr) 2px minmax(0, 220px);
  grid-template-rows: 28px auto;
  align-content: space-between;
  align-items: start;
  padding-top: var(--spacing-20);
}
.tl-mark { grid-row: 1; align-self: start; width: 2px; height: 16px; background: var(--color-sand); }
.tl-m1 { grid-column: 1; }
.tl-m2 { grid-column: 3; }
.tl-run { grid-row: 1; grid-column: 2; height: 1px; margin-top: 7px; background: var(--color-sand); }
.tl-gap {
  grid-row: 1;
  grid-column: 2;
  justify-self: center;
  align-self: start;
  margin: -14px 0 0;
  color: var(--color-sand);
  white-space: nowrap;
}
.tl-stop { grid-row: 2; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tl-s1 { grid-column: 1 / span 2; margin-right: var(--spacing-16); }
.tl-s2 { grid-column: 3 / span 2; }
.tl-when { color: var(--color-sand); }
.tl-sys { margin-top: var(--spacing-8); }
.tl-do {
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-linen);
}

/* 5. Private AI. UNFILLED 1px rectangles, which is what the Imagery rule
   specifies and what stops this well being a third copy of the filled row.
   The inbound line runs THROUGH the wall onto the Voice node; stopping at the
   wall said the outside world touches the perimeter and halts, which is the
   opposite of the layer's premise. Nothing leaves. */
/* Everything in this well was drawn at 1.67:1, so the layer whose whole claim
   is "this runs on hardware you own" was the palest object in the band. The
   perimeter and the inbound line CARRY the claim and take Sand at 11.38:1;
   the interior nodes are containment and stay Ink Line, per ruling AG.
   Centred, so the line lands on the node row by construction rather than by a
   hand-rolled offset that drifted at every breakpoint. */
.lv-private { flex-direction: row; align-items: stretch; gap: 0; }
.lv-private .perimeter { align-self: stretch; }
/* The line enters on the FIRST node row's centre, which is where a call would
   arrive, not on the box's midpoint between two rows. */
.inbound-label { align-self: flex-start; margin-top: calc(var(--spacing-20) + 20px - 8px); }
.inbound-line { align-self: flex-start; margin-top: calc(var(--spacing-20) + 20px); }

.inbound-label { flex: none; white-space: nowrap; }
.inbound-line {
  position: relative;
  z-index: 1;
  flex: none;
  width: calc(var(--spacing-24) + var(--spacing-20) + var(--spacing-8));
  height: 1px;
  background: var(--color-sand);
  margin-left: var(--spacing-8);
  margin-right: calc((var(--spacing-20) + var(--spacing-8)) * -1);
}
.perimeter {
  position: relative;
  box-sizing: border-box;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;   /* the perimeter's top is the well's top, so the first node
                                    row sits at a KNOWN offset and the inbound line can meet it
                                    by construction rather than by chasing a centred box */
  border: 1px solid var(--color-sand);
  border-radius: var(--radius-sm);
  padding: var(--spacing-20);
}
.perimeter-label,
.perimeter-edge {
  position: absolute;
  padding: 0 var(--spacing-8);
  background: var(--color-ink-elevated);   /* the panel, not the enclosure canvas beneath it */
}
.perimeter-label { top: -8px; left: var(--spacing-16); color: var(--color-sand); }
.perimeter-edge, .perimeter-label { z-index: 1; }
.perimeter-edge { bottom: -8px; right: var(--spacing-16); }
.p-nodes { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--spacing-8); }
.p-node {
  display: grid;
  place-items: center;
  box-sizing: border-box;
  min-height: 40px;
  padding: var(--spacing-8) var(--spacing-4);
  background: var(--color-ink);      /* recessed INTO the panel */
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
  color: var(--color-linen);
  text-align: center;
}
.p-node-sys { grid-column: 1 / -1; color: var(--color-sand); }
.p-foot {
  margin-top: var(--spacing-16);
  padding-top: var(--spacing-12);
  border-top: 1px solid var(--color-ink-line);
  color: var(--color-sand);
}

@media (max-width: 1179.98px) {
  .stack { --stack-inset: var(--spacing-20); }
  .layer {
    grid-template-columns: var(--stack-spine) minmax(0, 1fr);
    row-gap: var(--spacing-24);
    min-height: 640px;   /* clears the tallest natural entry ACROSS this range, measured at its narrow end */
    padding: var(--spacing-24) var(--stack-inset) var(--spacing-24) 0;
  }
  .layer:first-child { padding-top: calc(var(--spacing-24) + 1px); }
  .layer-text, .layer-view { grid-column: 2; padding-left: var(--stack-inset); }
  .layer-view { margin-left: 0; }
  .layer-body { max-width: 56ch; }
  .layer-foot { max-width: 56ch; }
  .layer-view { min-height: 0; }

  /* The time axis needs width. Stacked, it becomes a list, and the WAIT KEEPS
     ITS OWN ROW: the caption is a sibling of the run for exactly this reason,
     so hiding the run cannot delete the fact. */
  /* The axis ROTATES rather than disappearing. Hidden, the four days fell back
     onto their caption, which is the defect ruling AG exists to end; the wait
     is still physical, it is just measured downward now. */
  .lv-flow > .tl { height: auto; }
  /* Three explicit rows: a tick at day one, the run beside the wait, a tick at
     day five. Left to auto-placement all three landed in row one and the run
     measured the day-one paragraph. */
  .tl {
    grid-template-columns: 2px minmax(0, 1fr);
    grid-template-rows: auto auto auto;
    align-content: start;
    padding-top: 0;
    column-gap: var(--spacing-16);
  }
  .tl-mark { grid-column: 1; width: 16px; height: 2px; margin-left: -7px; align-self: start; }
  .tl-m1 { grid-row: 1; margin-top: 7px; }
  .tl-m2 { grid-row: 3; margin-top: 7px; }
  .tl-run {
    grid-column: 1;
    grid-row: 2;
    width: 1px;
    height: 100%;
    min-height: 48px;
    margin: 0 auto;
    background: var(--color-sand);
  }
  .tl-s1 { grid-row: 1; }
  .tl-gap { grid-row: 2; }
  .tl-s2 { grid-row: 3; }
  .tl-stop, .tl-gap { grid-column: 2; justify-self: stretch; margin: 0; }
  .tl-gap { align-self: center; padding: var(--spacing-20) 0; }
  .tl-stop { padding: 0; }
}
@media (max-width: 768px) {
  /* Wrapped, the line inherited space-between and was flung to the opposite
     edge, ending 29px above the perimeter with nothing at either end. Stacked,
     the label sits above the box and the line runs DOWN into its top edge. */
  .lv-private { flex-wrap: wrap; align-content: flex-start; justify-content: flex-start; align-items: flex-start; }
  /* margin-top 0: the row layout's 32px offset survived into the stack and
     dropped the label onto the perimeter's own label (MEASURED at 375, both
     at y 715..717, on the Private AI page). */
  .inbound-label { align-self: flex-start; margin-top: 0; }
  .inbound-line {
    align-self: flex-start;
    width: 1px;
    height: var(--spacing-16);
    margin: var(--spacing-8) 0 0 var(--spacing-12);
  }
  /* The perimeter starts where the line ends, and its own label moves to the
     right-hand end of the top edge: pulled up 8px with the label on the left
     it sat on "Dış dünya" (MEASURED at 375: 692..709 over 683..700). */
  .perimeter { flex: 1 0 100%; margin-top: 0; }
  .perimeter-label { left: auto; right: var(--spacing-16); }
  .p-nodes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* The row must be able to wrap from the moment the well narrows, not from the
   phone breakpoint. Between 481 and 619 it could not, and elia-design.md's Turkish
   binding is explicit that overflow-wrap is the guaranteed floor so a long
   compound can never push a card open. This one pushed it open by 1900px. */
@media (max-width: 1179.98px) {
  .act-row {
    min-height: 44px;
    flex-wrap: wrap;
    gap: var(--spacing-8) var(--spacing-12);
  }
  .act-sys { min-width: 0; }
  .act-do { flex: 1 1 100%; }
  /* A named speaker beside its line needs width neither has at phone size:
     the turn and the outcome stack, label over text. */
  .lv-turn, .lv-outcome {
    display: block;
  }
  .lv-who, .lv-outcome .mono {
    display: block;
    margin-bottom: var(--spacing-4);
  }
  .lv-outcome .lv-ref { margin-left: 0; margin-top: var(--spacing-4); }
}
@media (max-width: 480px) {
  .stack { --stack-spine: 44px; --stack-inset: var(--spacing-16); }
  .stack-head { min-height: 36px; height: auto; }
  .layer {
    min-height: 792px;   /* clears the tallest natural entry across 360 to 480, not just at 480 */
    padding: var(--spacing-20) var(--stack-inset) var(--spacing-20) 0;
  }
  .layer:first-child { padding-top: calc(var(--spacing-20) + 1px); }
  .layer-foot { grid-template-columns: minmax(0, 1fr); gap: var(--spacing-8); }
  /* Nothing may clip mid glyph at phone width: the rows wrap and grow. */
  .act-row,
  .act-sys { min-width: 0; }
  .act-do { flex: 1 1 100%; }
  .source { margin-left: var(--spacing-12); }
  .p-nodes { grid-template-columns: minmax(0, 1fr); }
  /* A separator that wraps to the head of the next line separates nothing. */
  .layer-meta .vrule { display: none; }
  .layer-meta, .lv-call-meta { gap: 4px 16px; flex-wrap: wrap; }
}

/* Integration flow */
/* L5, 2026-08-28: the diagram LEADS this band. Its old 48px top margin sat
   under a lede that no longer exists; the interval now belongs to the headline
   beneath it, which names what the diagram just showed. */
.integration-flow {
  display: flex;
  align-items: center;
  gap: 0;
  margin-top: 0;
}
#entegrasyonlar h2 { margin-top: var(--spacing-48); }
.elia-node {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 120px;
}
/* Ruling O, reinstated: the mark is DRAWN, not filled. A bare disc is the
   thing that ruling forbids. The circle keeps the Ember it was already
   counted for as budget type 9; the bars take Ink, which is the label colour
   the accent always carries, at 5.48:1. No new colour and no new radius: the
   circle is a circle, as --radius-dot always allowed. */
.elia-node-mark {
  width: 40px;
  height: 40px;
  flex: none;
}
.elia-node-mark svg { width: 100%; height: 100%; display: block; }
.mark-disc { fill: var(--color-ember); }
.mark-bar  { fill: var(--color-ink); }
.elia-node-name { font-size: 16px; }
.integration-edges { flex: 1; height: 340px; min-width: 0; margin-left: -56px; }
.elia-node { position: relative; z-index: 1; }
.edge-base { fill: none; stroke: var(--color-ink-haze); stroke-width: 1; }
/* A 24px dash TRAVELLING the path, per the Integration Row spec, not a
   permanent full-length stroke. Built as a full-length dash it left six
   static Ember lines standing on the Linen band forever, which is decorative
   accent: a finished write path is neither an action nor a live state, which
   is ruling AB's own test. The dash retires when it lands; the Ink Haze base
   path is what remains, because the CONNECTION is permanent and the WRITE is
   the event. */
.edge-ember {
  fill: none;
  stroke: var(--color-ember);
  stroke-width: 1;
  stroke-dasharray: 24 var(--edge-length, 1000);
  stroke-dashoffset: var(--edge-length, 1000);
  opacity: 0;
}
.integration-flow.drawn .edge-ember {
  animation: integration-edge-draw var(--dur-draw) var(--ease-signal) 1 both;
  animation-delay: calc(var(--edge-i) * var(--stagger));
  opacity: 1;
  transition: opacity var(--dur-base) var(--ease-exit);
}
.integration-flow.drawn.spent .edge-ember { opacity: 0; }
.system-tiles {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 220px;
}
.system-tile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: 56px;
  padding: 0 16px;
  box-sizing: border-box;
  background: var(--color-linen);
  border: 1px solid var(--color-linen-line);
  border-radius: var(--radius-sm);
}
.tile-name {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  line-height: var(--leading-micro);
  letter-spacing: var(--tracking-micro);
  font-weight: var(--weight-medium);
  color: var(--color-ink-slate);
}
.tile-cat { color: var(--color-ink-slate); }

.integration-edges-m { display: none; }

@media (max-width: 768px) {
  .integration-flow { flex-direction: column; gap: var(--spacing-24); }
  /* The six-edge fan needs horizontal room it does not have here; the node and
     the write do not. Only the fan is dropped. */
  .integration-edges { display: none; }
  .integration-edges-m {
    display: block;
    width: 24px;
    height: 56px;
    flex: none;
  }
  .system-tiles { width: 100%; display: grid; grid-template-columns: 1fr 1fr; }
  .band-dark { padding: var(--spacing-64) var(--gutter); }
}
@media (max-width: 480px) {
  .system-tiles { grid-template-columns: 1fr; }
}

/* ---- Piece D: proof, close, footer ---- */
#kanit { padding-top: var(--spacing-160); padding-bottom: var(--spacing-160); }
.stat-row {
  display: flex;
  justify-content: center;
  gap: var(--spacing-64);
  margin-top: var(--spacing-64);
}
.stat-block { text-align: center; }
.stat-number {
  font-family: var(--font-display);
  font-size: var(--text-stat);
  line-height: var(--leading-stat);
  letter-spacing: var(--tracking-stat);
  font-weight: var(--weight-light);
  font-variant-numeric: tabular-nums;
  color: var(--color-linen);
  margin: 0;
}
.stat-desc {
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-ink-mist);
  margin: 12px 0 0;
}

.band-close { padding-top: var(--spacing-160); padding-bottom: var(--spacing-160); }
.band-close h2 {
  font-size: var(--text-heading-lg);
  line-height: var(--leading-heading-lg);
  letter-spacing: var(--tracking-heading-lg);
  font-weight: var(--weight-light);
}
.close-cta { margin-top: var(--spacing-48); }

/* Footer: Ink Deep, hairline top, zero Ember, zero motion. */
.footer {
  background: var(--color-ink-deep);
  border-top: 1px solid var(--color-ink-line);
  padding: var(--spacing-96) var(--gutter) var(--spacing-40);
}
.footer-grid {
  display: grid;
  /* Three, not five. Two of the five held nothing once the placeholder links
     were removed, and a heading with nothing under it is worse than no
     heading. elia-design.md's Footer component is amended to match. */
  grid-template-columns: repeat(3, 1fr);
  gap: var(--spacing-32);
}
.footer-col { display: flex; flex-direction: column; gap: 10px; }
.footer-head {
  line-height: 1.36;   /* a display face must not inherit the body's 1.60 */
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: var(--weight-medium);
  color: var(--color-sand);
  margin: 0 0 4px;
}
.footer-col a {
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-ink-mist);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-signal);
}
.footer-col a:hover { color: var(--color-linen); }
.footer-bottom {
  display: flex;
  align-items: center;
  gap: var(--spacing-20);
  margin-top: var(--spacing-48);
  padding-top: var(--spacing-20);
  border-top: 1px solid var(--color-ink-line);
}
.footer-wordmark { font-size: 16px; }
.footer-copy { font-size: var(--text-caption); letter-spacing: var(--tracking-caption); color: var(--color-ink-mist); }
.footer-build { margin-left: auto; color: var(--color-ink-mist); }
.footer-legal {
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-caption);
  color: var(--color-ink-mist);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-signal);
}
.footer-legal:hover { color: var(--color-linen); }

@media (max-width: 768px) {
  .stat-row { flex-direction: column; gap: var(--spacing-40); }
  /* minmax(0,1fr), not 1fr: a bare 1fr floors at min-content, so the registered
     address pushed its column to 160px against the other's 120px and the two
     stopped being halves. The address wraps now instead of shoving. */
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
  /* One column on a phone. Two halves of a 360px screen give the registered
     address about 150px, which wraps it to five lines beside a column of
     three short links -- the address becomes the tallest thing in the footer
     by accident. */
  .footer-grid { grid-template-columns: minmax(0, 1fr); }
  /* Each bottom-row item on its own unbroken line: compressed legal links
     read as a rendering bug exactly where credibility is being claimed. */
  .footer-bottom { flex-direction: column; align-items: flex-start; gap: 10px; }
  .footer-bottom > * { white-space: nowrap; }
  .footer-build { margin-left: 0; }
}

/* ---- The intro transition ----
   Two named animations plus a CSS transition on the veil's mask radius.
   No new keyframe. The hero paints underneath from the first frame; this
   only covers it. Removed from the DOM the moment it ends or aborts. */
.intro {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
}
.intro-veil { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.intro-veil .veil-fill { fill: var(--color-sand); }

/* The Ink front. The hole grows, revealing the real hero beneath;
   the rim is the ring that sweeps to the edges. */
#intro-hole-circle, .rim-circle {
  r: 0;
  transition: r var(--intro-front, 900ms) var(--ease-exit);
}
.intro-rim {
  opacity: 1;
  transition: r var(--intro-front, 900ms) var(--ease-exit),
              transform var(--intro-front, 900ms) var(--ease-exit),
              opacity var(--intro-rim-fade, 420ms) linear;
}
.intro-rim.spent { opacity: 0; }
.intro-rim { stroke: var(--color-ember); stroke-width: 1; fill: none; }

/* Below 480 a centre circle covers the width long before the height, which
   shows a navy pill on cream bands. The front becomes a HORIZONTAL band,
   full width from the first frame, its two edges sweeping out through the
   top and bottom of a tall viewport. Full width from the start means no
   side margin can ever exist, so it cannot read as a slot or a pillarbox.
   Same causality, same two colours, still a transition, not a keyframe.
   The ring stays a ring above 480. */
#intro-hole-band, .rim-band {
  display: none;
  transform: scaleY(0);
  /* Off centre on purpose: two edges leaving in perfect mirror read as a
     letterbox opening. Offset, they read as a front. */
  transform-origin: 50% 44%;
  transition: transform var(--intro-front, 900ms) var(--ease-exit),
              opacity var(--intro-rim-fade, 420ms) linear;
}
.rim-band { stroke-width: 1; }
@media (max-width: 480px) {
  #intro-hole-circle, .rim-circle { display: none; }
  #intro-hole-band, .rim-band { display: block; }
}

.intro-dot {
  position: absolute;
  left: 50%; top: 50%;
  width: 40px; height: 40px;
  margin: -20px 0 0 -20px;
  border-radius: var(--radius-dot);
  background: var(--color-ember);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-signal);
}
.intro-dot.landed { opacity: 1; }
/* The dot retires with its ring: neither outlives the call landing. */
.intro-dot.retiring { opacity: 0; }
.intro-dot.retiring::after { opacity: 0; }
.intro-dot.landed::after {
  content: "";
  position: absolute; inset: 0;
  border: 1px solid var(--color-ember);
  border-radius: var(--radius-dot);
  animation: call-ring-ping var(--dur-ping) var(--ease-emit) 1 both;
}

/* Hero content waits behind the veil; the canvas and the bars do not. */
/* The veil never delays the hero. Its eyebrow, headline and subhead paint
   from the first frame and the front reveals the real thing as it passes.
   Only the elements that carry Ember wait, so the budget holds at two types
   while the veil is up: the intro signal, and the waveform. */
.intro-active .nav,
.intro-active .hero-cta,
.intro-active .call-card { opacity: 0; }
.intro-reveal .nav,
.intro-reveal .hero-cta,
.intro-reveal .call-card { opacity: 1; transition: opacity var(--dur-base) var(--ease-signal); }

@media (prefers-reduced-motion: reduce) {
  .intro { display: none; }
}

/* Footer company facts. Human prose in Inter; the tax registry number is
   machine metadata and takes the mono voice, per the record-write precedent. */
.footer-fact {
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-ink-mist);
}
a.footer-fact-id { text-decoration: none; }
a.footer-fact-id:hover .mono { color: var(--color-linen); }
.footer-fact-id .mono {
  color: var(--color-ink-mist);
  margin-left: var(--spacing-8);
  white-space: nowrap;
}

/* ================= The step rail =================
   The rail is pinned and the stops scroll past it. The active stop is a true
   state, the reader's own position, so it is allowed to change; it is a
   TRANSITION, not a loop, and costs no ambient period.
   The active mark is Linen against Ink Mist. Ember is not used here even
   where the budget would permit it: a reader crossing this section already
   passes the fixed nav CTA and a live console status, and a fourth accent
   on screen erodes the accent. Three is the ceiling, not the target. */

/* elia-design.md centres content on dark bands. A step rail is structured by
   nature and cannot centre, so the band's PROSE entry centres and the
   apparatus below it stays left aligned. */
/* L3 (cheap variant), 2026-08-28: the lede is gone and its 64px bottom margin
   moves here, because the interval belonged to the band, not to the sentence.
   The four stop labels below already say what the band does. */
.rail-entry {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: var(--spacing-64);
}

/* ---- T1: heading size expresses band WEIGHT, not register ----
   Heading size was a function of register: .band-dark h2 took heading-lg 44px
   and .band-light h2 took heading 36px, so every dark band shouted equally and
   every light band spoke equally, whatever the band was doing. That was
   inherited from the two-register model, never decided. Size now ranks the
   bands: hero 56, the two structural bands 44, the product band 36, the three
   supporting bands 28, and the close 56 so the page closes on the size it
   opened with.

   The WEIGHT rule is untouched -- 300 on Ink, 400 on Linen -- because the same
   numeric weight reads two different ways across the two registers, and that is
   an optical correction rather than a hierarchy decision.

   Only existing scale steps are used. No new size enters the system. */
/* T3: the close takes the DISPLAY step, the same one the hero opens on. It is
   the page's ask, and it is the only band besides the hero to reach 56px, so
   the page ends on the size it began with. Costs nothing: the step exists and
   is already fluid, clamping to 36px at phone widths exactly as the H1 does. */
#demo h2 {
  font-size: var(--text-display);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
}

#entegrasyonlar h2,
#randevu h2,
#sss h2 {
  font-size: var(--text-heading-sm);
  line-height: var(--leading-heading-sm);
  letter-spacing: var(--tracking-heading-sm);
}
.band-dark h2.rail-title { max-width: 26ch; }   /* .band-dark h2 outranks a bare class: this was dead for four runs */

.rail-layout {
  display: grid;
  grid-template-columns: 160px minmax(0, 1fr);
  column-gap: var(--spacing-64);
  align-items: start;
}

.rail {
  position: sticky;
  top: 152px;                 /* clears the 80px nav with room to breathe */
  display: flex;
  gap: var(--spacing-20);
}

/* The track reports two things: where the reader is, and how far through
   the sequence they have come. The fill is the second of those. */
.rail-track {
  position: relative;
  width: 2px;
  flex: none;
  background: var(--color-ink-line);
}
.rail-fill {
  position: absolute;
  left: 0; top: 0;
  width: 2px;
  height: 0;
  background: var(--color-linen);
  transition: height var(--dur-slow) var(--ease-signal);
}
.rail-dot {
  position: absolute;
  left: 50%;
  top: 0;
  width: 8px; height: 8px;
  margin-left: -4px;
  margin-top: -3px;
  border-radius: var(--radius-sm);
  background: var(--color-linen);
  transition: top var(--dur-slow) var(--ease-signal);
}

.rail-stops { list-style: none; margin: 0; padding: 0; }
.rail-stop {
  display: flex;
  align-items: center;
  height: 64px;               /* tap target, and the rail's step unit */
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;            /* it does something, so it says so */
  color: var(--color-ink-mist);
  transition: color var(--dur-fast) var(--ease-signal);
}
.rail-stop .label {
  font-family: var(--font-body);
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  font-weight: var(--weight-medium);
}
.rail-stop:hover { color: var(--color-sand); }
.rail-stop:focus-visible {
  outline: 2px solid var(--color-ember);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.rail-stop.is-active {
  color: var(--color-linen);
}
/* 600 is permitted on button labels by the Inter spec, and these are buttons,
   so the active stop carries colour AND weight rather than colour alone. */
.rail-stop.is-active .label { font-weight: var(--weight-semi); }

/* ---- Steps ---- */
.rail-steps { display: flex; flex-direction: column; gap: 120px; }
/* Text left, console right. The console is beside the words it belongs to,
   not beneath them, so the reader sees the claim and its evidence at once. */
.rail-step {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  column-gap: var(--spacing-48);
  align-items: start;
}
.rail-step .console { grid-column: 2; grid-row: 1 / span 3; align-self: center; }
.step-eyebrow, .rail-step h3, .step-body { grid-column: 1; }
.step-eyebrow { color: var(--color-ink-mist); margin: 0 0 12px; }
.rail-step h3 {
  font-size: var(--text-heading-sm);
  line-height: var(--leading-heading-sm);
  letter-spacing: var(--tracking-heading-sm);
  font-weight: var(--weight-light);
  color: var(--color-linen);
  max-width: 20ch;
  margin: 0;
}
.step-body {
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--color-ink-mist);
  max-width: 46ch;
  margin: 20px 0 0;
}

/* ================= The console =================
   Two nested surfaces, which is what makes it read as an application rather
   than a panel: an outer frame at Ink Elevated and an inner body at Ink.
   The separation is a surface step plus a 1px hairline. No shadow. */
.console {
  background: var(--color-ink-elevated);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.console-head {
  display: flex;
  align-items: center;
  gap: var(--spacing-8);
  height: 36px;
  padding: 0 var(--spacing-16);
  border-bottom: 1px solid var(--color-ink-line);
}
.console-title { color: var(--color-sand); }
.console-head .status-pill { margin-left: auto; }
.console-timer { margin-left: auto; color: var(--color-sand); }
/* The console is a raised object on the page, and its interior wells are
   recessed INTO it. The body previously took the page colour, which made the
   middle of the console read as a hole cut in the page rather than as the
   inside of a window: chrome raised, content at page level. Inverted. */
.console-body {
  background: var(--color-ink-elevated);
  padding: var(--spacing-20);
  min-height: 268px;                  /* all four stops stand the same height */
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.console-foot {
  margin: 0;
  padding: 12px var(--spacing-16);
  border-top: 1px solid var(--color-ink-line);
  font-size: var(--text-caption);
  /* The caption step's OWN line-height. It set the size and the tracking from
     the caption row of the type scale and then let line-height inherit the
     body's 1.60, so this rendered 13px at 1.60 -- above the floor, so never a
     violation, but not the step it claims to be. Ruling AA makes the type
     scale the authority per step; a step is its four values together, not the
     three that happened to be written down. */
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-caption);
  color: var(--color-sand);
}

/* ---- Stop 1: the systems the agent is bound to ---- */
.link-map {
  position: relative;
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) 208px;
  align-items: center;
  min-height: 132px;
}
/* A diagram node, per the Imagery rule: a 4px radius rectangle, never a
   circle. The circle is reserved for status dots, avatars and the mark. */
.link-node {
  display: grid;
  place-items: center;
  width: 56px; height: 36px;
  border-radius: var(--radius-sm);
  background: var(--color-sand-wash);
  border: 1px solid var(--color-ink-line);
  font-size: 16px;   /* the wordmark component supplies family and tone; 13 is the footer-header size */
}
.link-edges { width: 100%; height: 132px; overflow: visible; }
.link-base { fill: none; stroke: var(--color-ink-line); stroke-width: 1; }
.link-draw {
  fill: none;
  stroke: var(--color-ember);
  stroke-width: 1;
  stroke-dasharray: 24 1000;
  --edge-length: 1024;
}
.link-draw { opacity: 0; }
.console.is-live .link-draw {
  animation: integration-edge-draw var(--dur-draw) var(--ease-signal) 1 both;
  animation-delay: calc(var(--edge-i) * var(--stagger));
  /* The dash shows the direction of write while it travels. When the path is
     drawn the connection exists and the signal is over, so it leaves rather
     than sitting on the page as a permanent accent. */
  opacity: 1;
  transition: opacity var(--dur-base) var(--ease-exit);
}
.console.is-drawn .link-draw { opacity: 0; }
.link-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.link-list li {
  display: grid;
  grid-template-columns: minmax(0,1fr) auto;
  align-items: center;
  gap: 2px var(--spacing-8);
  padding: 8px 12px;
  background: var(--color-ink);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
}
.link-list .sys { color: var(--color-linen); }
.link-list .holds { grid-column: 1 / -1; font-size: var(--text-caption); letter-spacing: var(--tracking-caption); color: var(--color-ink-mist); }  /* on Ink: 4.79:1 */
.link-list .cat { color: var(--color-sand); }

/* ---- Stop 2: the taught process, at rest ---- */
.console-body.rules { display: grid; gap: 12px; }
.rule-row {
  padding: 12px 14px;
  background: var(--color-ink);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
}
.console.is-live .rule-row {
  animation: agent-line-reveal var(--dur-slow) var(--ease-signal) both;
  animation-delay: calc(var(--line-index) * var(--stagger));
}
.rule-head { display: flex; align-items: baseline; gap: var(--spacing-8); }
.rule-name {
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body-sm);
  font-weight: var(--weight-medium);
  color: var(--color-linen);
}
.rule-tag {
  margin-left: auto;
  color: var(--color-ink-mist);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
  padding: 2px 6px;
}


/* A status pill sitting ON an Ink Elevated console takes an Ink fill rather
   than the Ink Elevated one the component specifies for a dark band. Two
   reasons, and they agree: a pill the same colour as the surface under it has
   no separation at all, and Ink Mist on Ink Elevated measures 3.89:1 where
   the same colour on Ink measures 4.79:1. The surface step buys the contrast. */
.console .status-pill { background: var(--color-ink); }
.console .console-fields dd.is-empty { color: var(--color-sand); }   /* the placeholder is machine metadata, and Sand clears AA on Ink Elevated */
.rule-do {
  margin: 6px 0 0;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-ink-mist);
}

/* ---- Stop 3: the call, and the fields filling as it runs ---- */
.console-body.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 200px;
  gap: var(--spacing-20);
}
.console-transcript { display: flex; flex-direction: column; gap: 12px; }
.console-fields {
  margin: 0;
  padding-left: var(--spacing-20);
  border-left: 1px solid var(--color-ink-line);
  display: grid;
  gap: 14px;
  align-content: start;
}
.console-fields div { display: grid; gap: 2px; }
.console-fields dt { color: var(--color-sand); }
.console-fields dd {
  margin: 0;
  /* Reserved. The empty state is an 11px mono placeholder in a 15.95px box and
     the filled state is 14px Inter in a 22.4px box, so the console grew 6.45px
     at phone width the moment KONU filled -- and everything below it moved. */
  min-height: var(--spacing-24);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-linen);
}
/* The empty state is a machine placeholder in every slot, so the row does not
   look ragged before it fills. Once filled, the face difference is meaningful:
   PLAKA and RANDEVU are machine values, KONU is the agent's own words. */
.console-fields dd:not(.mono).is-empty {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  line-height: var(--leading-micro);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-micro);
  color: var(--color-sand);
}
.console-fields dd.mono { font-size: var(--text-micro); letter-spacing: var(--tracking-micro); }

/* ---- Stop 4: the commit ---- */
/* Dark-register write row. The light-register component put Ink text on Ink
   Elevated at 1.23:1 and Ink Slate at 1.86:1; both were effectively invisible. */
.console .write-row {
  background: var(--color-ink);
  border-color: var(--color-ink-line);
}
.console .write-field {
  color: var(--color-linen);
  letter-spacing: var(--tracking-body-sm);
}
.console .write-system { color: var(--color-sand); }
.console .write-ref {
  color: var(--color-sand);
  background: var(--color-ink-elevated);
  border-color: var(--color-ink-line);
}
/* The record the write lands in, so the join key from the call reappears at
   the moment of the commit. */
.write-record {
  display: grid;
  /* auto-fit, not repeat(3): three equal columns of minmax(0,1fr) collapse to
     72px at 360 and then let their own contents hang out of them, which is
     invisible until a word is longer than 72px. Turkish fitted by luck --
     RANDEVU and YARIN are short. English does not: APPOINTMENT is 82px and
     the word "appointment" is 84px, so both the label and the value spilled
     their cell. The row now drops to two columns when three cannot hold their
     content, and above 332px of interior it is still the same three columns
     it always was. A cell is sized by what is in it, in either language. */
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: var(--spacing-8) var(--spacing-16);
  padding: 12px 14px;
  margin-bottom: 12px;
  background: var(--color-ink);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
}
.write-record div { display: grid; gap: 2px; }
.write-record dt { color: var(--color-sand); }
.write-record dd {
  margin: 0;
  color: var(--color-linen);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body-sm);
}
.write-record dd.mono { font-size: var(--text-micro); letter-spacing: var(--tracking-micro); }

/* ---- Responsive ---- */
@media (max-width: 1024px) {
  .rail-layout { grid-template-columns: 1fr; row-gap: var(--spacing-40); }
  .rail {
    position: static;
    gap: var(--spacing-16);
  }
  .rail-track { display: none; }
  .rail-stops { display: flex; gap: var(--spacing-24); flex-wrap: wrap; }
  .rail-steps { gap: 80px; }
  .rail-step { grid-template-columns: 1fr; row-gap: var(--spacing-32); }
  .rail-step .console { grid-column: 1; grid-row: auto; }
  .step-body { max-width: 56ch; }
}
@media (max-width: 768px) {
  .console-body.split { grid-template-columns: 1fr; }
  .console-fields {
    padding-left: 0;
    padding-top: var(--spacing-16);
    border-left: 0;
    border-top: 1px solid var(--color-ink-line);
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .link-map { grid-template-columns: 56px minmax(0, 1fr); }
  .link-edges { display: none; }
  .link-list { grid-column: 1 / -1; margin-top: var(--spacing-16); }
}
@media (max-width: 480px) {
  /* The foot's terminal line grows from one wrapped line to two as the job
     completes, and the console grew 6px under it. Reserved, so the commit
     lands without the page moving.

     THE RESERVE WAS 64px AND THE TWO-LINE HEIGHT IS 66.49px, so it was 2.49px
     short and the console still moved on every commit -- in Turkish, before
     English existed. Measured constants drift the moment anything around them
     changes; this one had drifted from its own copy. Expressed in `lh` it is
     two lines of whatever line-height this element actually computes, plus its
     own padding and border, and it cannot be wrong in either language or at
     any type-scale change. English merely made it visible: it puts a third
     console foot on the two-line branch. */
  .console-foot { min-height: calc(2lh + 24px + 1px); box-sizing: border-box; }
  .rail-steps { gap: 64px; }
  .console-body { padding: var(--spacing-16); }
  .console-fields { grid-template-columns: 1fr; }
}

/* ---- The questions ----
   Left column asks, right column answers. Hairline separators, no cards:
   a question is not an object, it is a row. */
/* Centred on a dark band, per elia-design.md. The two-column sticky arrangement
   was a light-register composition sitting on Ink. */
.faq-layout { display: block; }
.faq-intro {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: var(--spacing-48);
}
.faq-intro h2 { margin-bottom: var(--spacing-16); }
.faq-list-wrap { max-width: 760px; margin: 0 auto; }
/* L8, 2026-08-28: the contact line and the address moved OUT of the band's
   head and into its foot. They were the fourth and fifth parts of an opening
   that already ran eyebrow, headline, lede -- and a reader wants an address
   after the answers have failed to help, not before they have read one. */
.faq-foot {
  text-align: center;
  margin-top: var(--spacing-48);
}
.faq-mail {
  display: inline-block;
  margin-top: var(--spacing-20);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-linen);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--color-ink-slate);
  transition: text-decoration-color var(--dur-fast) var(--ease-signal);
}
.faq-mail:hover { text-decoration-color: var(--color-linen); }

.faq-list { border-top: 1px solid var(--color-ink-line); }
.faq-item { transition: background-color var(--dur-base) var(--ease-signal); }
.faq-item { border-bottom: 1px solid var(--color-ink-line); }

.faq-q {
  display: flex;
  align-items: center;
  gap: var(--spacing-20);
  width: 100%;
  padding: var(--spacing-20) 0;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--color-linen);
  transition: color var(--dur-fast) var(--ease-signal);
}
.faq-q:hover { color: var(--color-sand); }
.faq-q:focus-visible {
  outline: 2px solid var(--color-ember);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.faq-q span:first-child { flex: 1; }

/* The sign is a plus that becomes a minus. One element, one rotation:
   the state is open or closed and the mark says which. */
.faq-sign {
  position: relative;
  flex: none;
  width: 12px; height: 12px;
}
.faq-sign::before,
.faq-sign::after {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 12px; height: 1px;
  background: var(--color-ink-mist);
  transition: transform var(--dur-base) var(--ease-signal),
              background-color var(--dur-fast) var(--ease-signal);
}
.faq-sign::after { transform: rotate(90deg); }
.faq-q[aria-expanded="true"] .faq-sign::after { transform: rotate(0deg); }
.faq-q[aria-expanded="true"] .faq-sign::before,
.faq-q[aria-expanded="true"] .faq-sign::after { background: var(--color-linen); }
/* The open row holds its state with a surface step and a weight step, so the
   state survives after the opening transition has finished. */
.faq-item:has(.faq-q[aria-expanded="true"]) {
  background: var(--color-sand-wash);
  border-radius: var(--radius-sm);
}
.faq-q[aria-expanded="true"] { font-weight: var(--weight-medium); }
.faq-item:has(.faq-q[aria-expanded="true"]) .faq-q,
.faq-item:has(.faq-q[aria-expanded="true"]) .faq-a > p { padding-left: var(--spacing-16); padding-right: var(--spacing-16); }

.faq-a {
  display: grid;
  grid-template-rows: 0fr;
  /* Closed, the panel was zero-height but still visible: all five answers sat
     in the accessibility tree and in find-in-page while the button reported
     aria-expanded="false". visibility removes them. Delayed by the duration on
     close so the collapse is still seen, undelayed on open. */
  visibility: hidden;
  transition: grid-template-rows var(--dur-slow) var(--ease-signal),
              visibility 0s linear var(--dur-slow);
}
.faq-a > p {
  overflow: hidden;
  margin: 0;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-sand);   /* the OPEN row's fill is Sand Wash, where Ink Mist measures 4.05:1 */
  max-width: 62ch;
}
.faq-q[aria-expanded="true"] + .faq-a {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows var(--dur-slow) var(--ease-signal),
              visibility 0s linear 0s;
}
.faq-q[aria-expanded="true"] + .faq-a > p { padding-bottom: var(--spacing-20); }

@media (max-width: 1024px) {
  .faq-intro { margin-bottom: var(--spacing-32); }
}

/* ---- The live queue ----
   A row of inbound call subjects where the movement is a real arrival: an
   entry lands, the row advances, the oldest leaves. Each entry encodes a call
   that arrived, so the motion is a state rather than a loop running for
   effect. Fixed slots and transform-only movement, so nothing on the page
   shifts position as entries arrive. */
.queue {
  position: relative;
  height: 40px;
  margin: calc(var(--spacing-32) * -1) 0 var(--spacing-64);
}
.queue-label {
  position: absolute;
  left: 0; top: 50%;
  transform: translateY(-50%);
  color: var(--color-ink-mist);
}
/* The mask lives on the TRACK, not the row: it was severing the label. */
.queue-track {
  position: absolute;
  inset: 0 0 0 96px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 82%, transparent 100%);
          mask-image: linear-gradient(90deg, #000 0, #000 82%, transparent 100%);
}
.queue-item {
  position: absolute;
  top: 4px;              /* centred by geometry, never by transform */
  left: 0;
  display: flex;
  align-items: center;
  gap: var(--spacing-8);
  height: 32px;
  padding: 0 14px;
  white-space: nowrap;
  background: var(--color-ink-elevated);
  border: 1px solid var(--color-ink-line);
  border-radius: var(--radius-sm);
  font-size: var(--text-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--color-linen);
  transition: left var(--dur-slow) var(--ease-signal),
              opacity var(--dur-base) var(--ease-exit);
}
.queue-item .mono { color: var(--color-sand); }   /* ruling T: Ink Mist is 3.89:1 on Ink Elevated */
.queue-item.is-arriving { animation: agent-line-reveal var(--dur-slow) var(--ease-signal) both; }
.queue-item.is-leaving { opacity: 0; }

@media (max-width: 768px) {
  .queue { margin-bottom: var(--spacing-48); }
  .queue-label { display: none; }
}

/* ================= The difference band =================
   Ruling BD, first draft. The rail's and the queue's own rules carry the
   index and the chips; this adds the second lane, the chip's status tag and
   the two-sided card. No Ember: the Elia side is marked by Sand and by the
   raised surface, and only for the step at the reading mark. */
.diff-sub { margin: var(--spacing-20) 0 0; max-width: 58ch; color: var(--color-ink-mist); }
/* The band's own top: the rail begins after the head. */
#fark .rail-layout { margin-top: var(--spacing-64); }

/* THE STEPS ARE STACKING CARDS (owner, ruling BE). Each card is sticky at
   the rail's own line plus 44px per card, so an arrived card stays, the next
   slides up over it, and 44px of every buried card -- its ordinal and its
   noun -- stays readable above the pile. Opaque, because a card has to cover
   the one under it. js/main.js writes --s (a small scale-down) and --veil (an
   Ink wash) from how deep a card is buried; both are transform and opacity.
   Sticky needs the pile to fit the viewport (the media rules below): there
   the cards simply follow each other. */
/* One card per screen of scroll (owner): the gap is the frame's height less
   a card, so each card's approach is about one screen. */
#fark .rail-steps { gap: max(160px, calc(100vh - 420px)); }
/* The hold after the last card. A spacer CHILD, not padding: a sticky box is
   kept inside its container's content box. */
#fark .rail-steps::after { content: ""; flex: none; height: 10vh; }
.diff-step.rail-step {
  display: block;
  position: sticky;
  top: calc(var(--stack-top, 152px) + var(--i, 0) * 22px);
  padding: var(--spacing-32);
  background: var(--color-ink-deep);
  border: 1px solid var(--color-ink-line);
  border-radius: 12px;
  box-shadow: 0 -18px 40px -12px rgba(5, 10, 18, 0.6);
  transform: scale(var(--s, 1));
  transform-origin: 50% 0;
  will-change: transform;
  transition: border-color var(--dur-slow) var(--ease-signal);
}
.diff-step:nth-child(1) { --i: 0; }
.diff-step:nth-child(2) { --i: 1; }
.diff-step:nth-child(3) { --i: 2; }
.diff-step:nth-child(4) { --i: 3; }
.diff-step:nth-child(5) { --i: 4; }
.diff-step.rail-step::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--color-ink);
  opacity: var(--veil, 0);
  pointer-events: none;
}
.diff-step .step-eyebrow { margin-bottom: var(--spacing-20); }
/* Below 1024 the rail is a row above the pile and it STICKS under the nav
   (owner: which card the reader is at must show on the phone too), so the
   cards begin below it. */
@media (max-width: 1024px) {
  #fark .rail { position: sticky; top: 91px; z-index: 5; background: var(--color-ink); padding: 8px 0; margin: 0; }
  /* One row, always: wrapped to two it was 84px and sat on the first card. */
  #fark .rail-stops { flex-wrap: nowrap; gap: var(--spacing-16); overflow-x: auto; }
  #fark .rail-stop { height: 40px; }
  #fark .rail-stop.is-active .label { box-shadow: 0 2px 0 0 var(--color-sand); }
  .diff-step.rail-step { --stack-top: 152px; padding: var(--spacing-24) var(--spacing-20); }
}
/* Phones stack too (owner, ruling BI): a phone card is ~260px and four
   at 44px offsets sit in 500px of an 812px frame. The zoomed-in browser
   stacks as well (owner); only a frame under 480px gets plain cards. */
@media (max-height: 480px) {
  .diff-step.rail-step { position: relative; top: auto; transform: none; box-shadow: none; }
  .diff-step.rail-step::after { display: none; }
  #fark .rail-steps { gap: var(--spacing-32); }
  #fark .rail-steps::after { display: none; }
}
/* The card's head is its number alone (owner); the nouns stay on the rail. */
.diff-step .step-eyebrow { display: flex; align-items: center; gap: 10px; font-size: 14px; color: var(--color-sand); }
.diff-step .step-eyebrow .vrule { width: 1px; height: 12px; background: var(--color-ink-line); }
.diff-step.rail-step h3 { max-width: 26ch; }
.diff-body { margin: var(--spacing-20) 0 0; max-width: 62ch; font-size: var(--text-body-lg); line-height: 1.6; color: var(--text-on-dark-secondary); }
/* The step the reader is at. */
.diff-step.rail-step.is-current { border-color: var(--color-sand); }
@media (max-width: 768px) {
}
@media (prefers-reduced-motion: reduce) { .diff-step.rail-step { transition: none; } }

/* The Neden ELIA? footnote, carrying the headline's asterisk (copy of
   2026-09-29). Under the rail's column on wide frames. */
.diff-foot { margin: var(--spacing-48) 0 0; padding-left: calc(160px + var(--spacing-64)); font-size: var(--text-body-sm); color: var(--color-ink-mist); max-width: none; }
@media (max-width: 1024px) { .diff-foot { padding-left: 0; } }

/* ---- Reading progress ----
   Ruling BE. A 3px bar over the nav on every page (js/progress.js), Sand, so
   it spends no Ember. It fades in once the page has moved. */
.read-progress {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 3px;
  z-index: 60;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-signal);
}
.read-progress.is-on { opacity: 1; }
.read-progress span {
  display: block;
  height: 100%;
  background: var(--color-sand);
  transform: scaleX(0);
  transform-origin: 0 50%;
}
@media (prefers-reduced-motion: reduce) { .read-progress { transition: none; } }

/* ---- Booking band ----
   The scheduler embed was built here and withdrawn: see the note in the
   markup. What remains is a clean band that sends the reader out. */
.booking-linkout { margin-top: var(--spacing-32); }


/* ---- Ruling T applied ----
   Ink Mist is certified against Ink and nowhere else. Every run below sits on
   Ink Elevated, where it measures 3.89:1, so it takes Sand at 8.47:1.
   The HAZIR deployment label is deliberately NOT in this list: ruling S gives
   it Ink Mist precisely to distinguish it from Sand, which is SAHADA. Those
   two rulings collide on this one element and the collision is recorded
   rather than resolved unilaterally. */
.call-card .call-card-timer,
.call-card .transcript-line.from-customer span:last-child,
.console .console-fields dd:not(.mono) { color: var(--color-sand); }

/* The ember dot is born at the band's own origin, never on bare Sand.
   Declared last on purpose: an identical-specificity rule earlier in the
   file loses the cascade, which is exactly how the first attempt failed. */
@media (max-width: 480px) {
  .intro-dot { top: 44%; }
}
