/* Cervo — shared stylesheet.
   Extracted from index.html 2026-09-11, when oryggi.html and um.html made a
   second and third copy of it the alternative. Every page links this; nothing
   here is page-scoped except by selector. The portal graphic's rules only
   match on the home page and cost the others nothing but bytes, which the
   cache pays once.

   The token block is the contract: DESIGN.md's frontmatter mirrors it, and
   .design-sync/ reads from there. Change a value here and change it there. */

:root{
  --basalt:#141618;
  --graphite:#1F2327;
  --rime:#EEEFF1;
  --bone:#D8D3C8;
  --mist:#868D95;
  --innsigli:#93342A;
  --ember:#D06A50;

  /* Reading greys. Slate carries every word of body copy on a light
     ground; chip-ink is the smallest type that still clears AA on both
     Rime and Paper. */
  --slate:#3A4046;
  --chip-ink:#5A6068;
  --paper:#fff;

  /* Corner rounding is one dial, the same mechanism as the portal's
     --radius-scale: every corner on the page is a multiple of it, so one
     number re-rounds the whole site. 1 is the shipped look (2px controls
     and chips, 16px chat card); 0 is fully square, 2 noticeably soft.
     Circles are the deliberate exemption — the seal, the dots, the send
     button stay round at every setting. */
  --radius-scale:1;
  --r-crisp:calc(2px * var(--radius-scale));   /* buttons, chips, focus rings */
  --r-card:calc(16px * var(--radius-scale));   /* chat card + bubbles */
  --r-tail:calc(5px * var(--radius-scale));    /* bubble tail corners */

  --display:'Epilogue',system-ui,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,monospace;
  --gut:clamp(20px,5vw,48px);

  --line-dark:rgba(238,239,241,.12);
  --line-light:rgba(20,22,24,.12);

  /* Photography is desaturated rather than colour, on one dial. The page
     spends its only saturation on Innsigli marking a source, so a colour
     photograph would outrank the seal the moment it landed. .62 keeps
     skin reading as skin, which is the whole point of putting a person
     on the page; grayscale(1) is the austere alternative if colour still
     fights the palette once real photographs are in. */
  --photo-filter:saturate(.62) contrast(1.03);
}

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  background:var(--rime);
  color:var(--basalt);
  font-family:var(--display);
  font-weight:400;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  /* Icelandic compounds run long: ársreikningaskrá, gervigreindarvinnslan. */
  overflow-wrap:break-word;
}
::selection{background:var(--innsigli);color:var(--rime)}

.wrap{width:min(1140px,calc(100% - 2*var(--gut)));margin:0 auto}

/* Icons are drawn in the antler's vocabulary: open strokes, round caps, one
   weight. A typed → or + is a character standing in for a mark. */
.ico{
  width:16px;height:16px;flex:0 0 auto;
  fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;
}

.mono{
  font-family:var(--mono);font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;
}

a{color:inherit;text-decoration:none}

/* Keyboard users fell back to the UA ring once, which is invisible on the
   glass header. The ring is the ground's own ink: innsigli and ember mean
   provenance and nothing else. */
:focus-visible{outline:2px solid var(--basalt);outline-offset:3px;border-radius:var(--r-crisp)}
.sec-dark :focus-visible,
.cta :focus-visible,
footer :focus-visible,
.skip:focus-visible{outline-color:var(--rime)}
main:focus{outline:none}

/* Eight screens on a phone with the anchor nav hidden below 900px. */
.skip{
  position:absolute;left:var(--gut);top:-100px;z-index:60;
  background:var(--basalt);color:var(--rime);
  font-family:var(--mono);font-size:11px;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;
  padding:13px 16px;border:1px solid var(--line-dark);border-radius:var(--r-crisp);
  transition:top .18s ease;
}
.skip:focus{top:12px}

/* ─────────────────────────── header ─────────────────────────── */
/* Light glass, matching the light hero it sits on: the old dark glass was
   tuned to blend over the dark hero and composites to a muddy grey over
   rime. Over the dark sections below it reads as a clean light bar. */
header{
  position:fixed;top:0;left:0;right:0;z-index:40;
  background:rgba(238,239,241,.7);
  /* 18px, not 14: at 14 a heading passing under the bar still read as
     words through the glass */
  backdrop-filter:blur(18px) saturate(120%);
  -webkit-backdrop-filter:blur(18px) saturate(120%);
  border-bottom:1px solid var(--line-light);
  transition:background .25s ease,border-color .25s ease;
}
/* The light glass over a dark section composites to a flat grey and its
   links fall to 4:1. While a dark section runs under the bar the header
   swaps ground: depth by ground, the same move the sections make. */
header.on-dark{background:rgba(20,22,24,.6);border-bottom-color:var(--line-dark)}
header.on-dark .wordmark{color:var(--rime)}
header.on-dark .nav-links a{color:var(--bone)}
header.on-dark .nav-links a:hover{color:var(--rime)}
header.on-dark .nav-cta{color:var(--rime)!important;border-color:rgba(216,211,200,.32)}
header.on-dark .nav-cta:hover{border-color:var(--bone);background:rgba(216,211,200,.06)}
header.on-dark :focus-visible{outline-color:var(--rime)}
nav{
  display:flex;align-items:center;justify-content:space-between;
  gap:16px;height:74px;
}
.wordmark{
  font-family:var(--display);font-weight:500;
  font-size:28px;letter-spacing:-.015em;color:var(--basalt);
  transition:color .25s ease;
}
.nav-links{display:flex;gap:26px;align-items:center}
.nav-links a{
  font-family:var(--mono);font-size:12px;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;color:var(--chip-ink);
  /* 19px of text is not a pointer target; the header is 74px tall */
  display:inline-flex;align-items:center;min-height:44px;
  transition:color .2s ease;
}
.nav-links a:hover{color:var(--basalt)}
/* outlined, not solid: the hero's Bókaðu kynningu directly below is the
   one solid primary in the viewport, and two identical dark chips in the
   same corner competed. This stays the quiet, always-there way in. */
.nav-cta{
  color:var(--basalt)!important;
  border:1px solid rgba(20,22,24,.28);
  padding:8px 15px;border-radius:var(--r-crisp);
  /* below 520px this and öryggi are the only navigation left; the label
     never wraps, it wrapped to two lines beside the wordmark on phones */
  display:inline-flex;align-items:center;min-height:44px;white-space:nowrap;
  transition:border-color .2s ease,background .2s ease,color .25s ease;
}
.nav-cta:hover{border-color:var(--basalt);background:rgba(20,22,24,.04)}

/* ─────────────────────────── hero ─────────────────────────── */
/* Light since 2026-09: the portal graphic beneath is a light-surface
   export, and hero + graphic read as one rime surface. The dark drift,
   grid and grain moved out with the dark ground. */
.hero{
  position:relative;
  background:var(--rime);color:var(--basalt);
  /* .hero-inner owns the vertical spacing here */
  padding:0;
}
/* fine film grain: archival depth, reads physical not startup */
.grain{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  opacity:.045;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.hero-inner{
  position:relative;z-index:2;
  /* almost no bottom padding: the graphic below carries its own headroom */
  padding:clamp(88px,7vw,104px) 0 clamp(4px,1vw,12px);
}
/* headline left, the two actions stacked on the right, bottom-aligned so
   the primary sits on the headline's baseline; the graphic follows */
.hero-head{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:clamp(32px,5vw,72px);
}
.hero h1{
  font-family:var(--display);font-weight:500;
  /* the floor is the old 520px pin: with a 1.5rem floor the headline
     dipped to 24px between 521 and 686px, smaller than it renders on a
     phone, so the scale was not monotonic */
  font-size:clamp(2.2rem,3.5vw,3.4rem);line-height:.98;
  letter-spacing:-.03em;color:var(--basalt);
  margin-bottom:0;
}
.hero h1 .dim{color:var(--chip-ink);display:block}
.hero .lede{
  font-size:1.15rem;line-height:1.55;color:var(--slate);
  max-width:56ch;margin:22px 0 0;
}
/* grain on the light ground too, one notch lighter than on basalt:
   the hero and the stage are one rime surface and read as one material */
.hero .grain,#cv-portal .grain{opacity:.035}
#cv-portal .grain{z-index:-1}
.actions{display:flex;gap:22px;align-items:center;flex-wrap:wrap}
.hero .actions{flex-direction:column;align-items:flex-end;gap:16px;flex:0 0 auto;padding-bottom:4px}
.btn-primary{
  background:var(--rime);color:var(--basalt);
  font-weight:500;font-size:.95rem;letter-spacing:-.01em;
  padding:13px 24px;border-radius:var(--r-crisp);
  transition:transform .18s ease,background .18s ease;
}
.btn-primary:hover{transform:translateY(-1px);background:var(--paper)}
/* the light hero inverts the pair; the dark cta keeps the rime original */
.hero .btn-primary{background:var(--basalt);color:var(--rime)}
.hero .btn-primary:hover{background:var(--graphite)}
.btn-text{
  font-family:var(--mono);font-size:11px;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;color:var(--mist);
  display:inline-flex;align-items:center;gap:8px;min-height:44px;
  transition:color .2s ease;
}
.btn-text:hover{color:var(--rime)}
/* mist is 2.9:1 on rime; chip-ink is the light-ground grey that clears AA */
.hero .btn-text{color:var(--chip-ink)}
.hero .btn-text:hover{color:var(--basalt)}
.btn-text .arw{display:inline-flex;line-height:0;transition:transform .2s ease}
.btn-text:hover .arw{transform:translateX(3px)}

/* The address is an identifier: mono, lowercase. The copy control appears
   only where the clipboard API exists, because a mailto: with no registered
   handler does nothing at all when clicked. */
.mailto{display:inline-flex;align-items:center;gap:14px;min-height:44px}
.mailto .addr{
  font-family:var(--mono);font-size:12px;font-weight:400;
  letter-spacing:.04em;color:var(--bone);user-select:all;
}
.copy{
  font-family:var(--mono);font-size:11px;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;color:var(--mist);
  background:none;border:0;padding:0;cursor:pointer;
  display:inline-flex;align-items:center;min-height:44px;
  transition:color .2s ease;
}
.copy:hover{color:var(--rime)}
.copy[hidden]{display:none}

/* Innsigli, doing its one job: marking a verified source */
.seal{width:6px;height:6px;border-radius:50%;background:var(--ember);flex:0 0 auto}

/* hero thread: the chat card, answering live. The track is pinned to the
   bottom of the window, so an arriving turn pushes the thread up and the
   oldest slides out under the header — the header's own edge is the cut,
   no mask needed. */
/* .chat is defined later and its `margin:0 auto` would win; auto margins on
   a grid item disable stretch, so the card would shrink to fit-content —
   and with the track absolutely positioned, fit-content is just the header.
   Outrank it rather than reorder the file. */
.hero .hero-chat{max-width:none;margin:0;width:100%}
.hero .hero-chat .chat-top{padding:14px 20px}
/* The live dot retired 2026-09-02: the thread visibly moves, and a second
   clock beside it said nothing. Its corner now says what the figures are. */
.stream{
  position:relative;
  height:clamp(408px,55vh,536px);
  overflow:hidden;
}
/* The inset belongs on the track: it is absolutely positioned, so left/right
   resolve against .stream's padding box and any padding there is ignored. */
.stream-track{
  position:absolute;left:0;right:0;bottom:0;
  display:flex;flex-direction:column;gap:13px;
  padding:0 22px 2px;
}
/* The track is bottom-pinned because arriving turns push the thread up. With
   no JS, or under reduced motion, nothing arrives and bottom-pinning left an
   arbitrary tail cut mid-answer. Static, it opens on the first question. */
html:not(.js) .stream-track{top:0;bottom:auto}
/* With JS the track is bottom-pinned, so the nine static exchanges opened
   on the tail of the ninth answer, mid-sentence, with no question above
   it. Prime the set to the last whole pair; arriving clones are appended
   as siblings of .stream-set, so this never hides them. */
.js .stream-set.primed .xch:not(:last-child){display:none}
.stream-set{display:flex;flex-direction:column;gap:13px}
.xch{display:flex;flex-direction:column;gap:13px}
/* narrower than the 84% default, and against a track that is now inset,
   so a bubble never runs to the card edge */
.stream .bubble{max-width:86%}
/* An arriving turn is measured, the track offset by its height, then
   released, so the thread rises into place instead of jumping. */
.js .stream-track.gliding{transition:transform .52s cubic-bezier(.22,.68,.28,1)}
.js .turn.pop{animation:pop .36s cubic-bezier(.2,.7,.3,1) both}
@keyframes pop{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
.js .answer-in{animation:fade-in .34s ease both}
@keyframes fade-in{from{opacity:0}to{opacity:1}}
/* thinking, for the beat between question and answer */
.dots{display:flex;align-items:center;gap:4px;padding:3px 2px}
.dots i{
  width:5px;height:5px;border-radius:50%;background:var(--mist);
  animation:blink 1.3s ease-in-out infinite;
}
.dots i:nth-child(2){animation-delay:.18s}
.dots i:nth-child(3){animation-delay:.36s}
@keyframes blink{0%,75%,100%{opacity:.22}38%{opacity:.9}}

/* ─────────────────────────── sections ─────────────────────────── */
/* 2026-09-11: the band was 112px top and bottom, which put ~1,650px of
   pure padding into an 8,050px page. The air is load-bearing here and is
   not being traded away wholesale; it is being spent where a boundary
   actually has work to do. */
section{padding:clamp(60px,6.6vw,94px) 0;border-top:1px solid var(--line-light);scroll-margin-top:88px}
/* A section that keeps the ground of the one above it does not need the
   full boundary: the hairline already divides them and the eye reads the
   shared ground as one movement. Spending the same air on a same-ground
   seam as on a Rime-to-Basalt seam is what made nine sections read as
   nine equal bands. Tightening the seam groups them instead, which is
   the cheapest rhythm on the page. */
.sec-cont{padding-top:clamp(34px,3.6vw,52px)}
.sec-head{max-width:660px;margin-bottom:44px}
.sec-head h2{
  font-family:var(--display);font-weight:500;
  font-size:clamp(2rem,4vw,3.1rem);line-height:1.05;
  letter-spacing:-.03em;margin-bottom:18px;
}
.sec-head p{font-size:1.08rem;color:var(--slate);max-width:60ch}
.sec-head p + p{margin-top:14px}

/* three-up register: the 1px gap over a hairline background draws the
   rules, so a single row gets verticals and no box */
.cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;background:var(--line-light)}
.cell{background:var(--rime);padding:34px 32px}
.cols .cell:first-child{padding-left:0}
/* two rows of three: each row's first cell sits flush on the container edge */
.cols .cell:nth-child(3n+1){padding-left:0}
/* Two-up variant of the cell register. Three live sections were all
   reg-rows and two of them sat back to back, so half the page's prose
   arrived in one repeated shape. The four ChatGPT contrasts are the set
   that wants it least: they are short, they are read as pairs rather
   than scanned as a list, and putting them on a grid both halves the
   section and breaks the repetition before it establishes. Same cell
   grammar as the three-up: Rime fill, no radius, no border, rules drawn
   by the 1px gap, each row's first cell flush to the container edge. */
.cols-2{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;
  background:var(--line-light);
  border-top:1px solid var(--line-light);border-bottom:1px solid var(--line-light);
}
.cols-2 .cell{display:flex;flex-direction:column;padding:30px 34px}
.cols-2 .cell:nth-child(2n+1){padding-left:0}
/* a 34ch measure was tuned for a 3-up column and leaves half a 2-up cell
   empty */
.cols-2 .cell p{max-width:48ch}
.cell h3{font-family:var(--display);font-weight:600;font-size:1.2rem;letter-spacing:-.02em;margin-bottom:10px}
.cell p{font-size:.98rem;color:var(--slate);max-width:34ch}
/* the paragraphs run to different lengths, so let the mocks sit on the
   floor of the cell instead of wherever the prose happens to end */
.cols .cell{display:flex;flex-direction:column}
.cols .cell p{margin-bottom:22px}
.cols .cell .mock{margin-top:auto}

/* Rows: a heading column, the prose beside it, a hairline beneath. Used
   where the facts must read at one weight rather than as equal tiles. */
.reg-rows{border-top:1px solid var(--line-light)}
.reg-rows .item{
  display:grid;grid-template-columns:minmax(0,21ch) minmax(0,1fr);
  gap:6px clamp(24px,4vw,64px);
  padding:26px 0;border-bottom:1px solid var(--line-light);
}
.reg-rows h3{
  font-family:var(--display);font-weight:600;font-size:1.06rem;
  letter-spacing:-.02em;color:var(--basalt);
}
.reg-rows p{font-size:.99rem;line-height:1.6;color:var(--slate);max-width:62ch}
.reg-rows .mock{margin-top:16px;max-width:340px}
.sec-dark .reg-rows{border-top-color:var(--line-dark)}
.sec-dark .reg-rows .item{border-bottom-color:var(--line-dark)}
.sec-dark .reg-rows h3{color:var(--rime)}
.sec-dark .reg-rows p{color:var(--bone)}

/* Each capability cell carries a small mock of the thing it describes, on
   the same argument as the hero thread: a page claiming to look inside the
   business should show something of itself. Markup, not images — and no
   frame or fill, so they read as objects living on the page rather than as
   a screenshot dropped into it. aria-hidden, since the copy already says it.
   Innsigli is the accent, as it is everywhere else on a light ground; ember
   stays exclusive to the source seal. */
.mock{margin-top:22px}
.mock .row-i{
  display:flex;align-items:center;gap:8px;
  padding:7px 0;border-top:1px solid var(--line-light);
}
.mock .row-i:first-child{border-top:none}
.mock .t{
  font-size:.82rem;line-height:1.3;flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* done, open, open — a list mid-week, not a finished one */
.mock .box{
  width:12px;height:12px;flex:0 0 auto;border-radius:var(--r-crisp);
  border:1px solid var(--mist);
}
.mock .box.on{
  background:var(--innsigli);border-color:var(--innsigli);
  position:relative;
}
.mock .box.on::after{
  content:"";position:absolute;left:3px;top:1px;
  width:3px;height:6px;border:solid var(--rime);
  border-width:0 1.5px 1.5px 0;transform:rotate(42deg);
}
.mock .chip{padding:2px 6px}
/* a depicted answer, with its receipts: the one-line version of the
   hero thread, ending in the seal and its chips like every answer */
.mock .ans{
  font-size:.85rem;line-height:1.45;color:var(--slate);
  padding-bottom:2px;
}

/* a line rather than bars: it reads as a series that keeps arriving, which
   is the claim the card makes. The lit endpoint is the latest figure. */
.spark{display:block;width:100%;height:auto;overflow:visible}
.spark .area{fill:rgba(147,52,42,.09)}
.spark .line{
  fill:none;stroke:var(--innsigli);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;
}
.spark .halo{fill:rgba(147,52,42,.18)}
.spark .end{fill:var(--innsigli)}

.mock .fig{
  display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  padding:7px 0;border-top:1px solid var(--line-light);
}
.mock .fig:first-child{border-top:none}
.mock .fig span{font-size:.82rem;color:var(--slate)}
.mock .fig b{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.02em}
.mock .fig.out{border-top-color:rgba(20,22,24,.28)}
.mock .fig.out span{color:var(--basalt)}
/* the figure the card is actually about */
.mock .fig.out b{color:var(--innsigli)}
.mock .chip.now{color:var(--innsigli);border-color:rgba(147,52,42,.32)}

/* a depicted thing says so: the label above a mock is the same voice as
   the chat card's tag, so a reader never takes a demo for a customer */
.mock-tag{
  margin-top:18px;
  font-family:var(--mono);font-size:10px;font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;color:var(--mist);
}
.mock-tag + .board,.mock-tag + .page{margin-top:8px}
/* chips in the dark key: the label pair rule, mist for chip-ink */
.sec-dark .chip{color:var(--mist);background:rgba(238,239,241,.04);border-color:var(--line-dark)}

/* the case page, depicted: a title with its state, three figures, and
   the pages it links to. The row beside it describes exactly this. */
.page{max-width:340px}
.page .ptitle{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  font-weight:600;font-size:.95rem;letter-spacing:-.02em;color:var(--rime);
  padding-bottom:9px;border-bottom:1px solid var(--line-dark);
}
.page .pfigs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0}
.page .pfigs > div{padding:9px 12px 9px 0;min-width:0}
.page .pfigs > div + div{border-left:1px solid var(--line-dark);padding-left:12px}
.page .plbl{
  display:block;font-family:var(--mono);font-size:9px;font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;color:var(--mist);margin-bottom:4px;
}
.page .pfigs b{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.02em;color:var(--bone);white-space:nowrap}
.page .plinks{padding-top:9px;border-top:1px solid var(--line-dark)}
.page .plinks .plbl{margin-bottom:6px}
.page .plink{
  display:inline-block;font-size:.8rem;color:var(--bone);margin-right:14px;
  border-bottom:1px solid var(--line-dark);
}

/* the status board, in the dark key: columns ruled by left borders on a
   transparent ground, per the same borders-not-gaps rule as every dark
   grid — opaque cells would cover the grain */
.board{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:0;
  margin-top:18px;
}
/* The one move the board makes: the sentence above it says a case that
   changes column is seen at once, so when the board scrolls into view one
   case crosses to Lokið and the row beneath it closes up. The markup holds
   the end state; the script parks the two items at their start positions
   and releases them, so no JS and reduced motion both show the board
   after the move. */
.board .bitem{transition:transform .55s cubic-bezier(.16,1,.3,1)}
.reg-rows .board{max-width:560px}
.board .bcol{border-left:1px solid var(--line-dark);padding:0 14px;min-width:0}
.board .bcol:first-child{border-left:none;padding-left:0}
.board .blbl{
  font-family:var(--mono);font-size:9px;font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;color:var(--mist);
  margin-bottom:6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.board .bitem{
  font-size:.78rem;line-height:1.35;color:var(--bone);
  padding:6px 0;border-top:1px solid var(--line-dark);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* the source register, grouped: the type labels turn a flat list of names
   into a browsable map of what the system actually reaches */
.sources{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;
  background:var(--line-light);
  border-top:1px solid var(--line-light);
  border-bottom:1px solid var(--line-light);
}
.src-group{background:var(--rime);padding:28px 26px}
.sources .src-group:first-child{padding-left:0}
.src-group .lbl{
  font-family:var(--mono);font-size:10px;font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;color:var(--chip-ink);
  margin-bottom:16px;
}
.src-group ul{list-style:none;display:flex;flex-direction:column;gap:9px}
.src-group li{
  font-family:var(--display);font-weight:600;
  font-size:1.02rem;letter-spacing:-.02em;
}
.sec-note{
  margin-top:26px;font-family:var(--mono);font-size:11px;font-weight:400;
  letter-spacing:.07em;color:var(--chip-ink);max-width:66ch;line-height:1.7;
}
.sec-dark .sec-note,.cta .sec-note{color:var(--mist)}

/* chat card: shared by the hero thread. The card and the portal disc are
   the same object, paper above rime, and both say so the same way: an
   18% hairline at the edge and the card lift beneath, reweighed for a
   light ground (the old 40% black was tuned to float over the dark
   hero's drift). */
.chat{max-width:680px;margin:0 auto;background:var(--rime);border-radius:var(--r-card);overflow:hidden;border:1px solid rgba(20,22,24,.18);box-shadow:0 24px 54px rgba(20,22,24,.14)}
.chat-top{display:flex;align-items:center;justify-content:space-between;padding:15px 20px;background:var(--paper);border-bottom:1px solid var(--line-light)}
.chat-top .tag{font-family:var(--mono);font-size:10px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--chip-ink)}
.turn{display:flex}
.turn.user{justify-content:flex-end}
.turn.bot{justify-content:flex-start}
.bubble{max-width:84%;padding:13px 16px;border-radius:var(--r-card)}
.turn.user .bubble{background:var(--basalt);color:var(--rime);border-bottom-right-radius:var(--r-tail)}
.turn.bot .bubble{background:var(--paper);color:var(--basalt);border:1px solid var(--line-light);border-bottom-left-radius:var(--r-tail)}
.bubble p{font-size:.98rem;line-height:1.55;color:inherit;max-width:none}
/* sources as labelled chips: each cited source is its own object, so a
   reader can see at a glance that an answer joined two systems */
.src{margin-top:11px;padding-top:11px;border-top:1px solid var(--line-light);display:flex;align-items:center;flex-wrap:wrap;gap:6px}
/* the verification strip over a numeric answer: what was checked before
   the figure went out, in the evidence face, ruled off from the prose */
.verify{
  font-family:var(--mono);font-size:10px;font-weight:400;letter-spacing:.05em;
  color:var(--chip-ink);margin-bottom:9px;padding-bottom:9px;
  border-bottom:1px solid var(--line-light);
}
.src .seal{margin-right:2px}
.chip{
  font-family:var(--mono);font-size:10px;font-weight:400;letter-spacing:.05em;
  color:var(--chip-ink);background:rgba(20,22,24,.03);
  border:1px solid var(--line-light);border-radius:var(--r-crisp);
  padding:3px 7px;white-space:nowrap;
}
.chat-input{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:13px 16px 13px 20px;background:var(--paper);border-top:1px solid var(--line-light)}
.chat-input .ph{font-size:.96rem;color:var(--chip-ink)}
.chat-input .send{width:32px;height:32px;border-radius:50%;background:var(--basalt);color:var(--rime);display:flex;align-items:center;justify-content:center;flex:0 0 auto}

/* ferlið: connected ledger */
.ledger{max-width:620px}
.row{display:grid;grid-template-columns:34px 1fr;gap:24px;position:relative;padding-bottom:40px}
.row:last-child{padding-bottom:0}
.marker{position:relative;display:flex;justify-content:center}
.dot{width:10px;height:10px;border-radius:50%;background:var(--mist);margin-top:6px;z-index:1}
.row:last-child .dot{background:transparent;border:1.5px solid var(--bone);width:9px;height:9px}
.vline{position:absolute;top:16px;bottom:-24px;left:50%;width:1px;transform:translateX(-50%);background:var(--line-light)}
.row:last-child .vline{display:none}
/* The ledger draws itself as the reader arrives: each dot lands as its
   row enters, then the line runs down to the next. The sequence is time,
   and the hollow last dot still says it continues. Static without JS. */
.js .row .dot{transform:scale(.5);opacity:.45;transition:transform .4s cubic-bezier(.16,1,.3,1),opacity .4s ease}
.js .row .vline{transform:translateX(-50%) scaleY(0);transform-origin:top;transition:transform .7s cubic-bezier(.16,1,.3,1) .15s}
.js .row.seen .dot{transform:none;opacity:1}
.js .row.seen .vline{transform:translateX(-50%) scaleY(1)}
/* chip-ink, not mist: 11px mono on Rime needs the light key's label
   colour to clear AA, per the label pairing rule */
.num{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.1em;color:var(--chip-ink);display:block;margin-bottom:7px}
.row h3{font-family:var(--display);font-weight:600;font-size:1.06rem;letter-spacing:-.02em;margin-bottom:7px}
.row p{font-size:.96rem;color:var(--slate)}

/* ─────────────────────────── photography ───────────────────────────
   The page carried no photograph and no person until now, which left a
   cautious buyer with nothing to place. A photograph is held to the same
   rules as every other object here: square edges (the 2px Rule leaves
   rounding to controls and the chat card), a hairline instead of a frame,
   no shadow (the One Shadow Rule reserves that for the answer card and
   the disc), and desaturated per --photo-filter so it cannot outrank the
   seal. The hairline is drawn as an overlay rather than a border so the
   aspect-ratio box stays exactly the size it claims.

   The one photograph today is the founder portrait (myndir/halldor.jpg,
   720x900, checked for AI-provenance markers before it shipped; it carries
   none). The grey fill under the image is what shows while it loads. */
.photo-fig{margin:0}
.photo{margin:0;position:relative;background:rgba(20,22,24,.045)}
.sec-dark .photo,.cta .photo{background:rgba(238,239,241,.05)}
.photo img{display:block;width:100%;height:100%;object-fit:cover;filter:var(--photo-filter)}
.photo::after{content:"";position:absolute;inset:0;pointer-events:none;border:1px solid var(--line-light)}
.sec-dark .photo::after,.cta .photo::after{border-color:var(--line-dark)}
.photo-portrait{aspect-ratio:4/5}

/* ─────────────────────────── stofnandi ───────────────────────────
   Cervo is a managed service, so the thing being bought is partly the
   person running it. The portrait column is narrow on purpose: this is an
   attribution, not a hero shot. */
.founder{display:grid;grid-template-columns:minmax(0,296px) minmax(0,1fr);gap:clamp(28px,5vw,64px);align-items:start}
.founder-quote{font-size:1.15rem;line-height:1.55;color:var(--basalt);max-width:56ch}
.founder-quote + .founder-quote{margin-top:16px}
.founder-id{margin-top:26px;padding-top:18px;border-top:1px solid var(--line-light)}
.founder-name{font-family:var(--display);font-weight:600;font-size:1.06rem;letter-spacing:-.02em;display:block}
.founder-role{
  font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.1em;
  text-transform:uppercase;color:var(--chip-ink);display:block;margin-top:6px;
}
.founder-mail{font-family:var(--mono);font-size:11px;letter-spacing:.06em;color:var(--chip-ink);display:inline-block;margin-top:10px}
.founder-mail:hover{color:var(--innsigli)}

/* algengar spurningar: hairline register, same grammar as .sources */
.faq{max-width:820px;border-top:1px solid var(--line-light)}
.faq details{border-bottom:1px solid var(--line-light)}
.faq summary{
  list-style:none;cursor:pointer;
  display:flex;align-items:baseline;justify-content:space-between;gap:24px;
  padding:22px 0;
  font-family:var(--display);font-weight:600;font-size:1.06rem;
  letter-spacing:-.02em;color:var(--basalt);
  transition:color .2s ease;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--innsigli)}
.faq summary .sign{
  color:var(--chip-ink);align-self:center;flex:0 0 auto;
  display:inline-flex;line-height:0;
  transition:transform .2s ease,color .2s ease;
}
.faq summary:hover .sign{color:var(--innsigli)}
.faq details[open] summary .sign{transform:rotate(45deg)}
.faq .answer{padding:0 0 24px;max-width:66ch}
.faq .answer p{font-size:.98rem;color:var(--slate)}

/* dark sections: the adaptation register and the custody section, to
   carry the weight of the offer's new half and of the trust argument */
.sec-dark{
  position:relative;overflow:hidden;
  background:var(--basalt);color:var(--rime);
  border-top:1px solid var(--line-dark);
}
.sec-dark .wrap{position:relative;z-index:2}
.sec-dark .grain{opacity:.04}
.sec-dark .sec-head h2{color:var(--rime)}
.sec-dark .sec-head p{color:var(--bone)}

/* cta: dark close */
.cta{position:relative;overflow:hidden;background:var(--basalt);color:var(--rime);border-top:1px solid var(--line-dark);text-align:center}
.cta .grain{opacity:.04}
.cta .wrap{position:relative;z-index:2}
.cta h2{font-family:var(--display);font-weight:500;font-size:clamp(2rem,4.4vw,3.2rem);letter-spacing:-.03em;line-height:1.04;margin-bottom:20px}
.cta p{color:var(--bone);font-size:1.08rem;max-width:52ch;margin:0 auto 36px}
.cta .actions{justify-content:center}

/* footer */
footer{background:var(--basalt);color:var(--mist);padding:34px 0 46px;border-top:1px solid var(--line-dark)}
.foot{display:flex;justify-content:space-between;align-items:center;gap:20px;flex-wrap:wrap}
/* the antler signs off beside the wordmark. Bone, not rime, so it sits
   under the name rather than competing with it, and it is the only place
   on the page the mark appears. */
.sig{display:flex;align-items:center;gap:11px}
.antler{
  width:30px;height:30px;flex:0 0 auto;
  color:var(--bone);opacity:.85;
  transition:opacity .2s ease;
}
.sig:hover .antler{opacity:1}
/* .wordmark carries color:var(--basalt) for the header; unset here it put
   basalt on the basalt footer at 1:1 and the name was invisible. Rime is
   the 15.7:1 pair, and it keeps the bone antler beneath the name. */
.foot .wordmark{font-size:19px;color:var(--rime)}
.foot .desc{font-family:var(--mono);font-size:10px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;color:var(--mist)}
/* Who the reader is handing their board minutes to. Mist on basalt is
   5.5:1; the pair that fails is mist on rime, not this one. */
.foot-meta{display:flex;flex-direction:column;align-items:flex-end;gap:7px;text-align:right}
.foot-meta .legal{font-family:var(--mono);font-size:11px;font-weight:400;letter-spacing:.06em;color:var(--mist)}

/* four columns of names get too narrow before the layout breakpoint does */
@media (max-width:1040px){
  .sources{grid-template-columns:repeat(2,minmax(0,1fr))}
  .sources .src-group:nth-child(odd){padding-left:0}
}
@media (max-width:900px){
  /* One column put the CTA between the headline and the sentence that
     says what this is, so the reader was asked to book before being told
     what for. display:contents lifts h1 and .actions into .hero-inner so
     the lede can be ordered between them. */
  .hero-inner{display:flex;flex-direction:column}
  .hero-head{display:contents}
  .hero h1{order:1}
  .hero .lede{order:2;margin-top:22px}
  .hero .actions{order:3;align-items:flex-start;padding-bottom:0;margin-top:32px;gap:20px}
  .cols,.cols-2{grid-template-columns:1fr}
  /* single column: no column left to inset from, and the rules run the
     full width of the wrap */
  .cols .cell,.cols-2 .cell{padding-left:0;padding-right:0}
  /* stacked, the 2-up's cells are back to being a list, so they take the
     row register's vertical rhythm rather than the grid's */
  .cols-2 .cell{padding-top:24px;padding-bottom:24px}
  .reg-rows .item{grid-template-columns:1fr;gap:8px}
  .nav-links{gap:18px}
  .founder{grid-template-columns:1fr;gap:30px}
  .founder .photo-portrait{max-width:248px}
}
/* At 390px three links plus the CTA ran into the wordmark. Öryggi is the one
   that always survives, and since 2026-09-11 it and um okkur are pages rather
   than anchors, so what a phone keeps is now the two destinations and the
   booking. Innleiðingin is the anchor that goes. */
@media (max-width:520px){
  .nav-links a[href="/#ferlid"]{display:none}
}
@media (max-width:620px){
  .sources{grid-template-columns:1fr}
  .sources .src-group{padding-left:0}
  /* the board folds to two columns; the rules that separated the lower
     pair now have to run horizontally, per the turned-rule rule */
  .board{grid-template-columns:repeat(2,minmax(0,1fr))}
  .board .bcol:nth-child(odd){border-left:none;padding-left:0}
  .board .bcol:nth-child(even){padding-right:0}
  .board .bcol:nth-child(n+3){border-top:1px solid var(--line-dark);margin-top:12px;padding-top:12px}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  /* .gliding is (0,3,0) and a media query adds no specificity, so the plain
     .js .stream-track override lost to it. Match the class. */
  .js .stream-track,.js .stream-track.gliding{transition:none}
  .js .turn.pop,.js .answer-in,.dots i{animation:none}
  /* the script returns early here, so the thread is static */
  .stream-track{top:0;bottom:auto}
  .btn-primary:hover{transform:none}
  .btn-text:hover .arw{transform:none}
  .faq summary .sign{transition:none}
  .skip{transition:none}
  header,.wordmark{transition:none}
  /* the ledger and the board show their end state, no draw and no move */
  .js .row .dot{transform:none;opacity:1;transition:none}
  .js .row .vline{transform:translateX(-50%);transition:none}
  .board .bitem{transition:none}
  #cv-portal [data-feed],#cv-portal [data-flowdash]{opacity:1;transition:none}
}

/* ─────────────────── portal hero graphic (motion) ───────────────────
   Everything else about the graphic is inline in its markup. */
/* .stream's 55vh clamp is meaningless in a fixed-height stage */
#cv-portal .stream{height:420px}
/* below 900px uniform scaling gives an unreadable miniature, so fit()
   switches the stage to a stack: chat first at natural size, then the
   svg cropped to the disc (fit swaps the viewBox), columns skipped -
   the caption below says the same in words. !important outranks the
   stage's inline layout styles. */
#cv-portal.cv-stack{height:auto!important}
#cv-portal.cv-stack [data-stage]{position:static!important;width:auto!important;height:auto!important}
#cv-portal.cv-stack [data-chatwrap]{position:static!important;width:100%!important;max-width:440px;margin:34px auto 0;padding:0 var(--gut);box-sizing:border-box}
#cv-portal.cv-stack [data-graph]{position:static!important;display:block;width:100%!important;height:auto!important}
#cv-portal.cv-stack [data-col]{display:none!important}
/* flows into and out of the crop would show as stubs at the disc edge */
#cv-portal.cv-stack [data-feed],#cv-portal.cv-stack [data-flowdash],
#cv-portal.cv-stack [data-exchange]{display:none}
#cv-portal [data-exchange-stack]{display:none}
#cv-portal.cv-stack [data-exchange-stack]{display:inline}
/* chat first, disc second */
#cv-portal.cv-stack [data-stage]{display:flex;flex-direction:column}
#cv-portal.cv-stack [data-chatwrap]{order:-1}
#cv-portal.cv-stack [data-labels]{font-size:15px}
/* the disc's shadow is a DOM circle under the svg, placed by fit() from
   the disc's viewBox position: a CSS shadow costs nothing per frame,
   where a filter on the circle would re-render with every drift tick.
   isolation lets it sit at z-index -1 above the rime and under the
   stage, which is static (and so paints above absolutes) when stacked. */
#cv-portal{isolation:isolate}
#cv-portal [data-disc-shadow]{
  position:absolute;z-index:-1;border-radius:50%;pointer-events:none;
  background:var(--paper);box-shadow:0 24px 54px rgba(20,22,24,.14);
}
/* room under the stacked disc for its shadow */
#cv-portal.cv-stack{padding-bottom:40px}
/* On a phone the graphic was 1,687px to deliver 90 words, the worst ratio
   on the page. The stream is the lever: 420px was tuned for the fixed
   desktop stage, where the thread sits beside the disc and has the height
   to spend. Stacked, it is the first thing under the headline and three
   exchanges are as much as anyone reads before scrolling. The loop and the
   bottom pin are untouched. */
#cv-portal.cv-stack .stream{height:330px}
/* Between 900 and 1200px the stage crops to the chat and the disc, at
   the scale those need to stay legible on a laptop, and the columns
   hand over to the register below; the feed lines would be stubs at the
   crop edge. */
#cv-portal.cv-mid [data-col]{display:none!important}
#cv-portal.cv-mid [data-feed],
#cv-portal.cv-mid [data-flowdash]{display:none}
/* the inflow switches on as the stage arrives: feed lines sit at half
   strength until the disc is well in view, then come up over a second.
   On the groups, not the paths, which the hover focus sets inline. */
#cv-portal [data-feed],#cv-portal [data-flowdash]{opacity:.5;transition:opacity 1s ease}
#cv-portal.cv-on [data-feed],#cv-portal.cv-on [data-flowdash]{opacity:1}
/* The inventory register: the two columns' names, wherever the stage
   cannot show the columns themselves. Same grammar as every light
   register, a ruled gap and a rule above and below. */
.cv-register{
  display:none;grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;
  background:var(--line-light);
  border-top:1px solid var(--line-light);border-bottom:1px solid var(--line-light);
  width:min(1140px,calc(100% - 2*var(--gut)));margin:12px auto 0;
}
.hero-graphic.cv-register-on .cv-register{display:grid}
.hero-graphic.cv-register-on .graphic-caption{margin-top:44px}
/* 2026-09-29: not on phones. Stacked below 900px, the two lists ran to 426px
   of names under the disc, and the caption beneath already says the systems
   and nearly fifty public sources feed the portal; the FAQ and the film's
   description name them. The cropped laptop stage (900-1200px) keeps the
   list, since there it stands in for columns that are cut off. */
#cv-portal.cv-stack ~ .cv-register{display:none}
.cv-register .reg-col{background:var(--rime);padding:22px 26px}
.cv-register .reg-col:first-child{padding-left:0}
.cv-register .reg-lbl{
  font-family:var(--mono);font-size:10px;font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;color:var(--chip-ink);
  margin-bottom:14px;
}
.cv-register ul{
  list-style:none;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:9px 16px;
}
.cv-register li{
  font-weight:600;font-size:1.02rem;letter-spacing:-.02em;color:var(--slate);
  transition:color .35s ease,transform .35s ease;
}
.cv-register li.cv-cite{color:var(--basalt);transform:translateX(4px)}
@media (max-width:520px){
  .cv-register{grid-template-columns:1fr}
  .cv-register .reg-col{padding-left:0;padding-right:0}
  /* fourteen source names at 1.02rem/600 wrapped inside a 187px track and
     cost 484px on a phone. These are an inventory being scanned, not copy
     being read, so they take the smaller size and a tighter gutter. */
  .cv-register li{font-size:.94rem}
  .cv-register ul{grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:7px 14px}
  .cv-register .reg-col{padding-top:18px;padding-bottom:18px}
  .cv-register .reg-lbl{margin-bottom:11px}
}
#cv-portal [data-scroll]{scrollbar-width:thin;scrollbar-color:rgba(20,22,24,.22) transparent}
#cv-portal [data-scroll]::-webkit-scrollbar{width:6px}
#cv-portal [data-scroll]::-webkit-scrollbar-thumb{background:rgba(20,22,24,.22);border-radius:2px}
/* citation pulse: when the thread lands an answer, the source rows and
   constellation it cites light briefly — the rows nudge toward the disc */
#cv-portal [data-list] > div,
#cv-portal [data-scroll] > div{transition:color .35s ease,transform .35s ease}
#cv-portal .cv-cite{color:#141618!important;transform:translateX(-4px)}
/* it follows the hero on the same rime surface: no section chrome, and the
   1440 stage centres itself on screens wider than it */
.hero-graphic{padding:0 0 clamp(48px,5vw,74px);border-top:none}
#cv-portal{max-width:1440px;margin:0 auto}
/* the caption under the graphic, in the Note voice: what flows in and
   what comes out, said once, under the picture that shows it. The
   slogan heading that stood here came out 2026-09-02. */
.graphic-caption{max-width:840px}
.graphic-caption .graphic-note{
  font-family:var(--mono);font-size:11px;font-weight:400;
  letter-spacing:.07em;line-height:1.7;color:var(--chip-ink);
}
/* stacked layout: the crop ends near the disc edge, so the caption needs
   its own air; on the full stage the stage's whitespace provides it */
@media (max-width:900px){
  .graphic-caption{margin-top:44px}
}

/* ─────────────────────────── interior pages ───────────────────────────
   Added 2026-09-11 with /oryggi and /um. The home page opens on a headline
   beside a booking and hands straight to the portal graphic; an interior page
   opens on a title, a lede and a way back, because a reader arriving here
   followed a link and needs to know where they landed. Everything below the
   head is the same register family the home page uses. */
.page-hero{background:var(--rime);color:var(--basalt);border-top:none;padding:0}
.page-hero-inner{position:relative;z-index:2;padding:clamp(72px,6vw,104px) 0 clamp(40px,4vw,56px)}
.page-hero h1{
  font-family:var(--display);font-weight:500;
  font-size:clamp(2.1rem,3.4vw,3.2rem);line-height:1.02;
  letter-spacing:-.03em;color:var(--basalt);margin:18px 0 0;max-width:19ch;
}
.page-hero .lede{
  font-size:1.15rem;line-height:1.55;color:var(--slate);
  max-width:58ch;margin-top:20px;
}
/* the way back is a provenance line, not a button: mono, quiet, in the
   evidence face, on the same argument as every other label on the page */
.crumb{
  font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.1em;
  text-transform:uppercase;color:var(--chip-ink);display:inline-block;
}
.crumb:hover{color:var(--innsigli)}
.crumb .arw{display:inline-block;margin-right:7px}
/* Long-form prose on an interior page, where the home page only ever carries
   registers. Capped at the reading measure and ruled like everything else. */
.prose{max-width:68ch}
.prose p{font-size:1.02rem;line-height:1.65;color:var(--slate)}
.prose p + p{margin-top:16px}
.prose h3{
  font-family:var(--display);font-weight:600;font-size:1.14rem;
  letter-spacing:-.02em;color:var(--basalt);margin:34px 0 10px;
}
.sec-dark .prose p{color:var(--bone)}
.sec-dark .prose h3{color:var(--rime)}
/* the home page's own link into a split-out page, sitting under the condensed
   version it replaced */
.read-on{
  display:inline-block;margin-top:30px;
  font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.1em;
  text-transform:uppercase;color:var(--chip-ink);
}
.read-on:hover{color:var(--innsigli)}
.sec-dark .read-on{color:var(--mist)}
.sec-dark .read-on:hover{color:var(--ember)}
.read-on .arw{display:inline-block;margin-left:7px;transition:transform .25s ease}
.read-on:hover .arw{transform:translateX(3px)}

/* Footer page list. The nav has four slots and a page site has more than four
   places; the footer is where the rest stay reachable, including the FAQ that
   gave up its nav slot on 2026-09-11. Mono at the Label size, because a list
   of destinations is signage rather than reading. */
.foot-nav{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px 18px;margin-bottom:4px}
.foot-nav a{
  font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.1em;
  text-transform:uppercase;color:var(--bone);
}
.foot-nav a:hover{color:var(--rime)}

/* ─────────────────────────── claims row ───────────────────────────
   The home page's custody band, compressed 2026-09-11 when /oryggi took the
   long version. It was a section head plus four row-register entries at 839px;
   the facts were never the weight, the shape was. Four equal columns ruled by
   left borders on transparent ground — the dark grid's own mechanism, the same
   one the status board uses — say the same four things in a third of the
   height.

   Equal weight across all four columns is the point and is not a layout
   preference: the outside-EEA disclosure is one of them, and a disclosure set
   smaller or lighter than the reassurances beside it has been demoted, which
   is the tell. It was promoted out of a footnote once already for exactly
   that. */
.claims{display:grid;grid-template-columns:repeat(4,minmax(0,1fr))}
/* three-up: the quick half of the adaptation register, where four would leave
   a column empty and a row register would spend a paragraph on each */
.claims-3{grid-template-columns:repeat(3,minmax(0,1fr))}
/* clears the last row register entry's own rule, so the three-up reads as the
   second movement of the section rather than as a sixth entry crowding the
   fifth */
.reg-rows + .claims{margin-top:30px}
.claims .claim{border-left:1px solid var(--line-dark);padding:0 22px}
.claims .claim:first-child{border-left:none;padding-left:0}
.claims h3{
  font-family:var(--display);font-weight:600;font-size:1.02rem;
  letter-spacing:-.02em;color:var(--rime);margin-bottom:9px;
}
.claims p{font-size:.92rem;line-height:1.55;color:var(--bone)}
@media (max-width:900px){
  /* four folds to 2x2; the lower pair turns its rules horizontal, per the
     Turned Rule Rule the status board follows. Three has no square to fold
     into, so it stacks. */
  .claims:not(.claims-3){grid-template-columns:repeat(2,minmax(0,1fr))}
  .claims:not(.claims-3) .claim:nth-child(odd){border-left:none;padding-left:0}
  .claims:not(.claims-3) .claim:nth-child(even){padding-right:0}
  .claims:not(.claims-3) .claim:nth-child(n+3){border-top:1px solid var(--line-dark);margin-top:18px;padding-top:18px}
  .claims-3{grid-template-columns:1fr}
  .claims-3 .claim{border-left:none;padding:0}
  .claims-3 .claim + .claim{border-top:1px solid var(--line-dark);margin-top:16px;padding-top:16px}
}
@media (max-width:520px){
  .claims{grid-template-columns:1fr}
  .claims .claim{border-left:none;padding:0}
  .claims .claim + .claim{border-top:1px solid var(--line-dark);margin-top:16px;padding-top:16px}
}


/* ── founder signature ──
   The home page's condensed founder block, reduced again on 2026-09-11 from a
   section with its own head to a signature sitting directly above the close.
   A face and a name at the point of booking is the job; the heading and lede
   that framed it were paying section rent for an introduction /um now makes in
   full. Centred rather than top-aligned, because a signature is one object
   rather than a column of prose beside a picture. */
.founder-sig{
  grid-template-columns:minmax(0,190px) minmax(0,1fr);
  gap:clamp(24px,3.5vw,46px);align-items:center;
}
.founder-sig .founder-quote{font-size:1.06rem;max-width:52ch}
/* the rule is a divider above an attribution, so it stops where the sentence
   above it stops rather than running the width of the column */
.founder-sig .founder-id{margin-top:20px;padding-top:15px;max-width:52ch}
@media (max-width:900px){
  .founder-sig{grid-template-columns:1fr;gap:26px}
  .founder-sig .photo-portrait{max-width:190px}
}

/* ─────────────────────────── hero: second button ───────────────────────────
   2026-09-28. The film earns a button of its own beside the booking: the
   booking stays the one filled button, and the film is the outlined one,
   because watching is the step before booking rather than an alternative to
   it. Same size and 2px corner as the primary, per the 2px Rule. The play
   glyph is drawn rather than typed, since U+25B6 renders as an emoji on iOS. */
.hero-btns{display:flex;flex-wrap:wrap;gap:12px;justify-content:flex-end}
.btn-secondary{
  display:inline-flex;align-items:center;gap:9px;
  font-weight:500;font-size:.95rem;letter-spacing:-.01em;
  padding:12px 22px;border-radius:var(--r-crisp);
  border:1px solid rgba(20,22,24,.28);color:var(--basalt);
  transition:border-color .18s ease,background .18s ease;
}
.btn-secondary:hover{border-color:var(--basalt);background:rgba(20,22,24,.04)}
.ico-play{width:12px;height:12px;fill:currentColor;stroke:none}

/* ─────────────────────────── the film ───────────────────────────
   A light film on Basalt: the ground gives it its edge, so it needs no
   shadow (the One Shadow Rule) and no frame beyond the dark hairline every
   photograph carries. Corners are --r-crisp, the site's own radius for a
   control-bearing rectangle; 16px belongs to the conversation alone. The
   16:9 box is reserved before the poster arrives, so nothing below it moves. */
.film{margin:0}
.film-frame{position:relative;aspect-ratio:16/9;max-width:100%;border-radius:var(--r-crisp);overflow:hidden;background:#E9EAEC}
.film-frame::after{content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;border:1px solid var(--line-dark)}
.film-frame video{display:block;width:100%;height:100%;object-fit:cover}
.film-cap{margin-top:22px;font-size:1.02rem;line-height:1.6;color:var(--bone);max-width:72ch}
/* the text alternative: closed by default, the same register as the FAQ */
.film-text{margin-top:22px;border-top:1px solid var(--line-dark);max-width:72ch}
.film-text summary{
  list-style:none;cursor:pointer;padding:16px 0 4px;
  font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.1em;
  text-transform:uppercase;color:var(--mist);
}
.film-text summary::-webkit-details-marker{display:none}
.film-text summary::after{content:" +";}
.film-text[open] summary::after{content:" −";}
.film-text summary:hover{color:var(--rime)}
.film-text ol{margin:12px 0 0;padding-left:1.2em;color:var(--bone);font-size:.94rem;line-height:1.6}
.film-text li + li{margin-top:8px}
.film-text b{color:var(--rime);font-weight:600}

/* ─────────────────────────── custody: two groups ───────────────────────────
   The security band carries two claim rows since 2026-09-28, each under a
   mono group head: where the data is, and what the AI may do. Claims under a
   group head are h4, so the headings still read as an outline. */
.claims-group{
  font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.12em;
  text-transform:uppercase;color:var(--mist);margin:0 0 18px;
}
.claims + .claims-group{margin-top:44px}
.claims h4{
  font-family:var(--display);font-weight:600;font-size:1.02rem;
  letter-spacing:-.02em;color:var(--rime);margin-bottom:9px;
}
.read-ons{display:flex;flex-wrap:wrap;gap:6px 34px;margin-top:22px}
.read-ons .read-on{margin-top:0}
/* the register's "more during adaptation" row is a note, not a system */
.cv-register li.reg-more{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--chip-ink);align-self:center}

@media (max-width:900px){
  .hero-btns{justify-content:flex-start}
}

/* The film has no audio track, so Blink and WebKit's mute button does
   nothing; hide it rather than offer a control with no effect. */
.film-frame video::-webkit-media-controls-mute-button,
.film-frame video::-webkit-media-controls-volume-slider{display:none}

/* Nav at the narrowest phones: wordmark, two links and the booking do not fit
   in 375px, and "um okkur" was breaking onto two lines with the booking
   pressed against the edge. Links never wrap; below 420px um okkur leaves the
   header, since the footer carries it, and öryggi stays as the one link a
   cautious reader came for. */
.nav-links a{white-space:nowrap}
@media (max-width:420px){
  .nav-links a[href="/um"]{display:none}
}

/* Claim headings are two to six words in a narrow column; balanced wrapping
   keeps a lone last word ("…og sá sem / spyr") off a line of its own.
   Browsers without text-wrap simply wrap as before. */
.claims h3,.claims h4{text-wrap:balance}

/* the diagram caption is two short paragraphs; without a gap they read as one */
.graphic-caption .graphic-note + .graphic-note{margin-top:8px}
