/* =============================================================================
   domainchaos.com — the paper edition
   -----------------------------------------------------------------------------
   The previous build was a single 30KB file: a dark console, one orange, a
   glow on every edge, and every colour in it a literal. This is its opposite
   and deliberately so, in the register labs.llc uses — white paper, one ink,
   a great deal of air, and type doing the work the glow used to do.

   The whole system is five decisions:

     ink      #1E262B   near-black with the blue left in, never pure #000
     paper    #FFFFFF
     deep     #11161C   the dark band, one step colder than the ink
     line     a 12% ink hairline; there are no heavy borders anywhere
     measure  1265px

   This sheet is the LIGHT edition and the canonical one. The dark edition is
   assets/css/dark.css: an override sheet scoped to html[data-dark], loaded
   after this one, holding nothing but the literals this file could not express
   as tokens. Nothing in this file may be edited to serve the dark edition —
   that is what the override sheet is for, and keeping that boundary is what
   stops the light edition regressing every time the dark one is touched.

   THE ONE RULE when adding to this file: prefer a token. A declaration that
   reads var(--ink) or var(--line) is already correct in both editions and
   needs no second line anywhere. Only a literal has to be answered twice, and
   the literals that cost the most are the ones where a colour is a SURFACE
   rather than text — a band, a panel, a field. Those are the ones the audit in
   tools/audit.js counts.
   ========================================================================== */

/* ------------------------------------------------------------------ webfont
   DM Sans, self-hosted, the same two files labs.llc serves. It used to be an
   @import of fonts.googleapis.com sitting at the top of an inline <style> —
   which is the worst of every option: a render-blocking stylesheet, on a
   third-party origin, discovered only after the HTML parser reached the middle
   of the document, in a page that otherwise made no network request at all
   before first paint.

   Variable across both axes the sheet uses (opsz 9-40, wght 200-700), so the
   four-weight inversion the design rests on is 94KB of woff2 rather than
   twelve separate faces. Split on the same unicode ranges Google splits on, so
   a page of English never downloads the accented block. */
@font-face {
    font-family: 'DM Sans';
    font-style: normal;
    font-weight: 200 700;
    font-display: swap;
    src: url('../fonts/dm-sans-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                   U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                   U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'DM Sans';
    font-style: normal;
    font-weight: 200 700;
    font-display: swap;
    src: url('../fonts/dm-sans-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                   U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                   U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    --ink:        #1E262B;
    --ink-77:     rgba(30, 38, 43, .77);
    /* The secondary ink, at .64 rather than .55. .55 measures 3.6:1 on the
       paper, under the 4.5:1 body-text floor, and this token carries most of
       the small type on the site: every eyebrow, every field label, every
       registrar name, the whole of the results table's second line. At .64 it
       measures 4.7:1 and is still plainly the quieter of the two inks. */
    --ink-55:     rgba(30, 38, 43, .64);
    --paper:      #ffffff;
    --tint:       #FAFAFA;  /* recessed panel ground, added for Network Labs */
    --deep:       #11161C;
    --deep-soft:  #171E26;
    --line:       rgba(30, 38, 43, .12);
    --line-soft:  rgba(30, 38, 43, .07);
    /* The inverse hairline: for rules drawn ON the deep band while the page
       itself is light. The dark edition has to flip this one the other way or
       those rules draw white on white. */
    --line-dark:  rgba(255, 255, 255, .13);
    --muted:      #717171;

    /* DomainChaos was #ff8800 throughout — a screen orange, chosen against
       #0a0a0a. It measures 2.1:1 on white, so on paper it is not an accent, it
       is a highlighter. The lineage survives as the burnt print red of the
       same family; the dark edition takes it back up to #F97316, which is the
       original orange one step calmer and holds on the deep ground. Used for
       hairlines, eyebrows and live indicators only — never as a large fill. */
    --accent:     #C2410C;
    /* The accent as a FILL, with dark type on it. Inking a colour is right for
       type and wrong for a solid block, so the two are separate tokens and the
       fill keeps its saturation. */
    --accent-fill: #FB923C;
    --on-accent:  #2A1206;

    /* ------------------------------------------------------------- semantics
       The status of a domain is the one place this site needs colour to carry
       meaning, so these four are the only hues besides the accent.

       Every one of them is three steps down its scale from where a dark-ground
       palette would put it. #00cc66 — the old build's "AVAILABLE" — measures
       1.8:1 on white; at #15803D it is 4.9:1 and still unmistakably green. The
       dark edition moves all four back up; see dark.css. */
    --free:       #15803D;   /* available            */
    --taken:      #B91C1C;   /* registered           */
    --unsure:     #B45309;   /* could not determine  */
    --info:       #1D4ED8;   /* links, social        */
    --free-wash:   rgba(21, 128, 61, .07);
    --taken-wash:  rgba(185, 28, 28, .06);
    --unsure-wash: rgba(180, 83, 9, .07);

    --measure:    1265px;
    --gutter:     clamp(20px, 5vw, 56px);

    /* The height of the sticky header, published as a token because two things
       have to agree about it: the header, and every anchor target on the page.
       A heading scrolled to the top of the viewport lands underneath a sticky
       bar unless something subtracts the bar first. */
    --nav-h:      74px;
    --band:       clamp(56px, 6.4vw, 96px);
    --ease:       cubic-bezier(.22, .61, .36, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* Applied to anything with an id rather than to a hand-kept list of sections:
   a scroll margin costs nothing on an element nobody ever scrolls to, and a
   list is a thing to forget to update. */
[id] { scroll-margin-top: calc(var(--nav-h) + 14px); }

body {
    margin: 0;
    background: var(--paper);
    color: var(--ink-77);
    font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
                 Helvetica, Arial, sans-serif;
    font-size: 17px;
    line-height: 1.62;
    /* R4: the floor, by inheritance. Set the base readable and thin only what
       is deliberately large. The opposite order leaks — anything with no class
       of its own inherits the thin weight from a wrapper, and you end up with
       11px labels at weight 300 that you cannot find a rule for. */
    font-weight: 400;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4 { color: var(--ink); margin: 0; font-weight: 600; }

.d1 {
    font-size: clamp(2.1rem, 5.2vw, 3.9rem);
    font-weight: 200; letter-spacing: -.035em; line-height: 1.09;
}
.d2 {
    font-size: clamp(1.75rem, 3.5vw, 2.77rem);
    font-weight: 600; letter-spacing: -.04em; line-height: 1.06;
}
.d3 {
    font-size: clamp(1.25rem, 2vw, 1.6rem);
    font-weight: 300; letter-spacing: -.028em; line-height: 1.22;
}

/* The eyebrow. Every band opens with one; it is the only place small-caps
   tracking appears, so it reads as a system label rather than as text. 700,
   because tracking thins a face further and 500 at this size on paper is a
   smear. */
.eyebrow {
    display: flex; align-items: center; gap: .7rem;
    font-size: .688rem; font-weight: 700;
    letter-spacing: .19em; text-transform: uppercase;
    color: var(--ink-55);
    margin: 0 0 1.6rem;
}
.eyebrow::before { content: ''; width: 26px; height: 1px; background: var(--accent); flex: 0 0 auto; }
.eyebrow.on-deep { color: rgba(255, 255, 255, .62); }

.lede {
    font-size: clamp(1.02rem, 1.35vw, 1.19rem);
    line-height: 1.6; font-weight: 300; color: var(--ink-77);
    max-width: 62ch;
}
.lede + .lede { margin-top: 1rem; }

a { color: inherit; }

.wrap { max-width: var(--measure); margin: 0 auto; padding-inline: var(--gutter); }
.band { padding-block: var(--band); }
/* ------------------------------------------------------------------ the seam
   --band is a band's internal room, but what a reader sees between two
   sections is the void, and the void is not the padding. Where an unpainted
   band meets another the two paddings stack and the void is 2x--band; where
   one meets the deep band only half of it is white, because the other half is
   painted and reads as the band rather than as a gap. One uniform rule, and
   the visible white on the front page ran 101px to 262px across seven seams.

   So the seam is halved on both sides wherever two unpainted bands touch and
   left whole against a painted one. Every void is then --band, whatever it
   stands next to. The tint counts as unpainted on purpose: #FAFAFA against
   #FFFFFF is not a boundary the eye stops at. :has() is what makes the
   trailing half knowable, and where it is missing the band simply keeps the
   whole padding it shipped with.
   ------------------------------------------------------------------------ */
.band:not(.band--deep) + .band:not(.band--deep) { padding-top: calc(var(--band) * .5); }
.band:not(.band--deep):has(+ .band:not(.band--deep)) { padding-bottom: calc(var(--band) * .5); }
/* A hairline between two bands is a divider drawn IN the void, not a block
   that fills it, so the seam is still doubled and still wants halving. */
.band:not(.band--deep) + .rule + .band:not(.band--deep) { padding-top: calc(var(--band) * .5); }
.band:not(.band--deep):has(+ .rule + .band:not(.band--deep)) { padding-bottom: calc(var(--band) * .5); }

/* ---------------------------------------------------------------------------
   THE DEEP BAND

   The ink tokens are re-declared here rather than a list of `.band--deep .x`
   overrides being kept downstream. Everything on this sheet paints its
   secondary text with var(--ink-55) and its hairlines with var(--line), and
   every one of those would be near-black on a near-black ground the moment the
   component was used inside a deep band.

   --ink stays a FILL colour in a handful of places — the filled button, the
   pressed segment — so those are restated below rather than inheriting a white
   block with white type in it.
   ------------------------------------------------------------------------ */
.band--deep {
    --ink:        #FFFFFF;
    --ink-77:     rgba(255, 255, 255, .72);
    --ink-55:     rgba(255, 255, 255, .58);
    --line:       rgba(255, 255, 255, .16);
    --line-soft:  rgba(255, 255, 255, .09);
    --accent:     #F97316;
    --muted:      #8A9199;
    /* The semantic hues go back up their scale on a dark ground — the same
       three steps, in the other direction. See R6. */
    --free:       #4ADE80;
    --taken:      #F87171;
    --unsure:     #FBBF24;
    --info:       #93C5FD;

    background: var(--deep); color: var(--ink-77);
}
.band--deep h1, .band--deep h2, .band--deep h3, .band--deep h4 { color: #fff; }

/* The places --ink is a background rather than a text colour. */
.band--deep .btn                     { background: #fff; color: var(--deep); }
.band--deep .btn:hover               { background: rgba(255, 255, 255, .86); }
.band--deep .btn--ghost              { background: transparent; color: #fff; border-color: rgba(255,255,255,.38); }
.band--deep .btn--ghost:hover        { background: #fff; color: var(--deep); border-color: #fff; }
.band--deep .seg__b[aria-pressed="true"] { background: #fff; border-color: #fff; color: var(--deep); }

.band--tint { background: #FAFAFA; }
.rule { height: 1px; background: var(--line); border: 0; margin: 0; }

/* =============================================================================
   NAV
   ========================================================================== */

.nav {
    position: sticky; top: 0; z-index: 60;
    background: rgba(255, 255, 255, .86);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    border-bottom: 1px solid var(--line-soft);
}
.nav__in {
    max-width: var(--measure); margin: 0 auto; padding: 0 var(--gutter);
    height: var(--nav-h); display: flex; align-items: center; gap: 1rem;
}
.nav__mark { display: flex; align-items: center; gap: .8rem; text-decoration: none; margin-right: auto; }
/* The mark. No box, no ring, no fill.

   The old build ringed a photographic disc in 4px of orange with a 45px glow;
   the rewrite before this one swapped that for a hairline and a border-radius,
   which was quieter but was still a circle drawn around a logo that already had
   one. Two edges, concentric, neither of them content.

   A wordmark on paper needs no edge at all: the letterforms are the shape, and
   the thing that separates them from the page is the page. Height is set here
   and width is left to the viewBox so the 86:24 proportion cannot be squashed
   the way an <img> with two hard attributes squashed the old one.

   The colour is inherited, not declared — currentColor in the SVG picks up
   whatever --ink resolves to in this edition, which is the entire reason it can
   be one file for both. */
.nav__logo { display: block; height: 17px; width: auto; color: var(--ink); }

/* The mark is a <div> of two links now — the labs.llc plate and the local
   wordmark — so each half re-declares the flex row the single anchor used to
   be. The plate's height is set here and its width left to the 189:80 ratio,
   for the same no-squashing reason as the wordmark above. */
.nav__mark a { display: flex; align-items: center; gap: .8rem; text-decoration: none; }
.nav__plate { display: block; height: 28px; width: auto; }
.nav__mark b {
    font-size: .95rem; font-weight: 600; letter-spacing: -.03em; color: var(--ink);
}
.nav__mark span {
    font-size: .6rem; font-weight: 700; letter-spacing: .32em;
    text-transform: uppercase; color: var(--ink-55);
    padding-left: .8rem; border-left: 1px solid var(--line);
}
@media (max-width: 980px) { .nav__mark span { display: none; } }

.nav__links { display: flex; align-items: center; gap: 1.9rem; }
@media (max-width: 1100px) { .nav__links { display: none; } }
.nav__links a {
    text-decoration: none; font-size: .875rem; font-weight: 500;
    color: var(--ink-77); letter-spacing: -.01em; position: relative; padding-block: .4rem;
}
.nav__links a::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: 0;
    height: 1px; background: var(--ink); transform: scaleX(0); transform-origin: left;
    transition: transform .32s var(--ease);
}
.nav__links a:hover::after, .nav__links a[aria-current]::after { transform: scaleX(1); }
.nav__links a[aria-current] { color: var(--ink); }

/* ---------------------------------------------------------------------------
   THE EDITION PILL

   Lifted whole from labs.llc, because it is the same control doing the same
   job and a visitor who has met one should not have to learn the other. Two
   editions of this page — this one, paper, and indexdark.html — and the pill
   is where a visitor moves between them.

   Deliberately a segmented control rather than another nav link: the two are
   alternatives to each other, not destinations alongside Generator and
   Registrars, and a segmented control is the one shape that says so without a
   word of explanation.

   Exactly one segment carries .is-on, and it is written into the markup rather
   than worked out at runtime, because on any given page the answer is a
   constant: this file is always the light one. tools/mkdark.py moves it.

   The moving part is a single thumb behind both segments, not a background on
   whichever segment is lit. That is what lets it slide: on hover it travels to
   the segment under the cursor and previews the switch before the click.
   ------------------------------------------------------------------------ */
.mode-pill {
    position: relative; flex: 0 0 auto;
    display: inline-flex; align-items: center;
    padding: 3px; border-radius: 999px;
    border: 1px solid var(--line);
    /* A shallow well, so the thumb reads as sitting in the track rather than
       floating on the navbar. Both values are ink at single digits of alpha. */
    background: linear-gradient(180deg, rgba(30,38,43,.045), rgba(30,38,43,.025));
    box-shadow: inset 0 1px 2px rgba(30, 38, 43, .055);
}
.mode-pill__thumb {
    position: absolute; z-index: 0;
    top: 3px; bottom: 3px; left: 3px; width: calc(50% - 3px);
    border-radius: 999px; background: var(--ink);
    box-shadow: 0 1px 2px rgba(30, 38, 43, .26), 0 6px 18px rgba(30, 38, 43, .14);
    transition: transform .42s var(--ease);
}
/* Which half is lit. The class is on the container and written into the
   markup: on any one page the answer never changes. */
.mode-pill--dark .mode-pill__thumb { transform: translateX(100%); }

/* Hover preview. There are exactly two segments, so "the unlit one is hovered"
   already says which side the thumb belongs on and the rule needs no position
   selector — which matters, because the lit segment is a <span> and the unlit
   one an <a>, and a :first-of-type / :last-of-type pair counts types. Where
   :has is unsupported the pill simply does not preview, which costs nothing. */
.mode-pill:has(.mode-pill__seg:not(.is-on):hover) .mode-pill__thumb { transform: translateX(100%); }
.mode-pill--dark:has(.mode-pill__seg:not(.is-on):hover) .mode-pill__thumb { transform: none; }

.mode-pill__seg {
    position: relative; z-index: 1;
    display: inline-flex; align-items: center; justify-content: center;
    /* Both segments hold the same width, because the thumb is half the track
       and an uneven split would leave it short of one end. */
    min-width: 2.5rem; padding: .4rem .45rem; border-radius: 999px;
    text-decoration: none; color: var(--ink-55);
    transition: color .32s var(--ease);
}
/* The lit segment is a <span>, not a link — it is the page you are already on,
   and a link to here is a reload that costs a round trip and returns the same
   document. */
.mode-pill__seg.is-on { color: var(--paper); cursor: default; }
/* The fallback where :has is missing and the thumb therefore cannot move: the
   unlit segment darkens in place. It must not go to paper — with no thumb
   underneath, paper on the track is a label that vanishes. */
.mode-pill__seg:not(.is-on):hover { color: var(--ink); }
/* While a segment is hovered the thumb is under IT, so the lit colour follows
   the thumb rather than the class. Equal specificity, later wins. */
.mode-pill:has(.mode-pill__seg:hover) .mode-pill__seg.is-on { color: var(--ink-55); }
.mode-pill:has(.mode-pill__seg:hover) .mode-pill__seg:hover { color: var(--paper); }
.mode-pill__seg:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* 13px, and the same 13 is written on the <svg> tag itself as width and
   height. That duplication is the point: an SVG with a viewBox and no
   dimensions of its own falls back to 300x150 when no stylesheet reaches it. */
.mode-pill__i { width: 13px; height: 13px; flex: 0 0 auto; display: block; }

@media (prefers-reduced-motion: reduce) { .mode-pill__thumb { transition: none; } }

/* The hamburger. At every width — it opens the whole menu rather than a fold
   of the header, so on a wide screen the navbar's section links and the menu's
   tools are two different offers rather than the same one twice. */
.nav__burger {
    display: flex; width: 40px; height: 40px; padding: 0;
    background: transparent; border: 1px solid var(--line); border-radius: 8px;
    cursor: pointer; align-items: center; justify-content: center;
    color: var(--ink);
    transition: border-color .24s var(--ease);
}
.nav__burger:hover { border-color: var(--ink); }
.nav__burger svg { display: block; }
/* transform-box: view-box puts the origin in the icon's own coordinate space
   rather than on the line's own zero-height box, and the translate has to come
   second — CSS applies transform functions right to left. */
.nav__burger line {
    transform-box: view-box; transform-origin: 9px 6px;
    transition: transform .28s var(--ease);
}
.nav__burger[aria-expanded="true"] .nav__burger-t { transform: rotate(45deg) translateY(2.5px); }
.nav__burger[aria-expanded="true"] .nav__burger-b { transform: rotate(-45deg) translateY(-2.5px); }
@media (prefers-reduced-motion: reduce) { .nav__burger line { transition: none; } }

/* THE HEADER ON A PHONE. Three things have to fit inside 335 usable pixels at
   375 and 280 at 320: the mark, the edition pill, and the way into the rest of
   the site. Everything here is measured against those two numbers. */
@media (max-width: 1100px) { .nav__in { gap: .9rem; } }
@media (max-width: 640px) {
    :root { --nav-h: 62px; }
    .nav__in { gap: .55rem; }
    .nav__mark b { font-size: .86rem; }
    /* A segment is a glyph in a box, and the box is the tap target. The glyph
       stays at 13px — it is meant to be small — and what grows is the box. */
    .mode-pill__seg { min-width: 1.9rem; padding: .58rem .4rem; }
    /* No ring on a phone: the burger is the only thing in that corner and the
       outline was the heaviest object in the bar for no work it was doing.
       44px is the smallest a finger reliably hits. */
    .nav__burger { width: 44px; height: 44px; border-color: transparent; }
    .nav__burger:hover { border-color: transparent; }
    .nav__in > .btn { display: none; }
}
@media (max-width: 380px) { .nav__mark b { display: none; } }

/* =============================================================================
   THE MENU
   ========================================================================== */
.menu[hidden] { display: none; }
.menu {
    position: fixed; inset: 0; z-index: 200; display: block;
    /* Clipped: on the way out the scroll lock is released the instant close()
       runs while the panel is still travelling, and an unclipped panel sitting
       outside the viewport for those 360ms is a horizontal scrollbar that
       appears and leaves for no visible reason. */
    overflow: hidden;
}
.menu__scrim {
    position: absolute; inset: 0;
    /* A scrim exists to dim what is behind it, so it stays dark in both
       editions — see R2. It is the one black wash on this sheet that the dark
       edition does not re-polarise. */
    background: rgba(17, 22, 28, .38);
    -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
    opacity: 0; transition: opacity .32s var(--ease);
}
.menu.is-open .menu__scrim { opacity: 1; }
.menu__panel {
    position: absolute; top: 0; right: 0; height: 100%;
    width: 100%; max-width: 404px;
    background: var(--paper);
    border-left: 1px solid var(--line);
    box-shadow: -24px 0 60px rgba(30, 38, 43, .10);
    display: flex; flex-direction: column;
    transform: translateX(100%);
    transition: transform .36s var(--ease);
}
.menu.is-open .menu__panel { transform: none; }
/* The panel takes focus itself on open so a screen reader reads the dialog's
   label. It is a container, not a control, and the sheet-wide :focus-visible
   rule was drawing a 2px accent ring around all 404 pixels of it. */
.menu__panel:focus, .menu__panel:focus-visible { outline: none; }
@media (prefers-reduced-motion: reduce) { .menu__scrim, .menu__panel { transition: none; } }

.menu__head {
    flex: 0 0 auto; height: 74px;
    display: flex; align-items: center; gap: .8rem;
    padding: 0 1.15rem 0 1.4rem;
    border-bottom: 1px solid var(--line-soft);
}
.menu__logo { display: block; height: 24px; width: auto; }
.menu__title {
    font-size: .6rem; font-weight: 700; letter-spacing: .3em; text-transform: uppercase;
    color: var(--ink-55); padding-left: .8rem; border-left: 1px solid var(--line);
    margin-right: auto;
}
.menu__x {
    width: 34px; height: 34px; flex: 0 0 auto; padding: 0;
    display: flex; align-items: center; justify-content: center;
    background: transparent; border: 1px solid var(--line); border-radius: 8px;
    color: var(--ink-55); cursor: pointer;
    transition: border-color .24s var(--ease), color .24s var(--ease);
}
.menu__x:hover { border-color: var(--ink); color: var(--ink); }
.menu__x svg { width: 13px; height: 13px; }
@media (max-width: 640px) { .menu__x { width: 44px; height: 44px; } }

.menu__search {
    flex: 0 0 auto; position: relative;
    padding: .9rem 1.4rem;
    border-bottom: 1px solid var(--line-soft);
    background: var(--paper);
}
.menu__search svg {
    position: absolute; left: 2.05rem; top: 50%; transform: translateY(-50%);
    width: 13px; height: 13px; color: var(--ink-55); pointer-events: none;
}
.menu__q {
    font: inherit; font-size: .88rem; font-weight: 500; width: 100%;
    padding: .6rem 2.1rem .6rem 2.05rem;
    color: var(--ink); background: rgba(30, 38, 43, .035);
    /* --line is a rule between two things that are already there; a text input
       is a box that has to announce itself, so it gets a real border. */
    border: 1px solid rgba(30, 38, 43, .52); border-radius: 8px;
    transition: border-color .24s var(--ease), background .24s var(--ease);
    -webkit-appearance: none; appearance: none;
}
.menu__q::placeholder { color: var(--ink-55); font-weight: 400; }
.menu__q::-webkit-search-cancel-button { display: none; }
.menu__q:focus { outline: none; border-color: var(--ink); background: var(--paper); }
.menu__q:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Safari on iOS zooms the page when a focused input is under 16px, and a zoomed
   page carries the 404px panel — and the field that was just tapped — off the
   visual viewport. 16px is the threshold at which it does not, so the field
   takes it wherever the zoom can happen. Matched on the pointer rather than on
   a width: a phone held sideways is 932px wide and still zooms. */
@media (hover: none) and (pointer: coarse) {
    .menu__q { font-size: 16px; }
}
.menu__clear {
    position: absolute; right: 2rem; top: 50%; transform: translateY(-50%);
    width: 22px; height: 22px; padding: 0; display: flex;
    align-items: center; justify-content: center;
    background: transparent; border: 0; border-radius: 6px;
    color: var(--ink-55); cursor: pointer;
}
.menu__clear[hidden] { display: none; }
.menu__clear:hover { color: var(--ink); background: rgba(30, 38, 43, .06); }
.menu__clear svg { width: 10px; height: 10px; }

.menu__count {
    flex: 0 0 auto; margin: 0; padding: .55rem 1.4rem 0;
    font-size: .62rem; font-weight: 700; letter-spacing: .18em;
    text-transform: uppercase; color: var(--ink-55);
}
.menu__count b { color: var(--ink); font-weight: 700; }
.menu__count[data-filtered="1"] b { color: var(--accent); }

.menu__body { flex: 1 1 auto; overflow-y: auto; padding: 1.1rem 1.4rem 1.6rem; }
.menu__sec + .menu__sec { margin-top: 1.7rem; }
.menu__sec[hidden] { display: none; }
.menu__h {
    display: flex; align-items: center; gap: .8rem;
    font-size: .6rem; font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
    color: var(--ink-55); margin: 0 0 .5rem;
}
.menu__h::after { content: ''; height: 1px; background: var(--line); flex: 1 1 auto; }
.menu__row {
    display: flex; align-items: baseline; gap: .7rem;
    padding: .62rem 0; border-bottom: 1px solid var(--line-soft);
    text-decoration: none; color: var(--ink-77);
    transition: padding-left .2s var(--ease), color .2s var(--ease);
}
.menu__row:hover { color: var(--ink); padding-left: .5rem; }
.menu__row[hidden] { display: none; }
.menu__row:last-child { border-bottom: 0; }
.menu__l { flex: 1 1 auto; min-width: 0; }
.menu__l b { display: block; font-size: .9rem; font-weight: 600; letter-spacing: -.015em; color: var(--ink); }
.menu__l span { display: block; font-size: .74rem; font-weight: 400; color: var(--ink-55); line-height: 1.4; }
.menu__go { flex: 0 0 auto; color: var(--ink-55); font-size: .8rem; font-style: normal; }
.menu__empty { margin: 1.4rem 0 0; text-align: center; font-size: .82rem; color: var(--ink-55); }
.menu__empty[hidden] { display: none; }

.menu__foot {
    flex: 0 0 auto; padding: 1rem 1.4rem;
    border-top: 1px solid var(--line-soft); background: var(--paper);
    display: flex; justify-content: center;
}
/* The footer's copy of the pill is the same control, so it is the same size: a
   segmented pill held to its own width and centred, one step larger than the
   header's because a panel footer has the room. Stretched to the full width of
   the panel it reads as a broken button rather than as the pill above. */
.menu__foot .mode-pill { display: inline-flex; width: auto; }
.menu__foot .mode-pill__seg { flex: 0 0 auto; min-width: 3.6rem; padding: .6rem .8rem; }
@media (max-width: 460px) { .menu__panel { max-width: 100%; } }

/* =============================================================================
   BUTTONS
   ========================================================================== */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .6rem;
    font: inherit; font-size: .82rem; font-weight: 600; letter-spacing: .02em;
    padding: .72rem 1.15rem; border-radius: 8px;
    border: 1px solid transparent; background: var(--ink); color: #fff;
    text-decoration: none; cursor: pointer;
    transition: background .25s var(--ease), color .25s var(--ease),
                border-color .25s var(--ease), transform .25s var(--ease);
}
.btn:hover { background: #000; transform: translateY(-1px); }
.btn:active { transform: none; }
.btn[disabled] { opacity: .45; cursor: not-allowed; transform: none; }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--ghost:hover { background: var(--ink); color: #fff; border-color: var(--ink); }
.btn--sm { font-size: .72rem; padding: .5rem .8rem; }
.btn--outline {
    background: transparent; color: #fff; border-color: rgba(255, 255, 255, .45);
    text-transform: uppercase; font-size: .72rem; letter-spacing: .13em; font-weight: 600;
    padding: .82rem 1.35rem;
}
.btn--outline:hover { background: #fff; color: var(--ink); border-color: #fff; }
.btn i { transition: transform .25s var(--ease); font-style: normal; }
.btn:hover i { transform: translateX(3px); }

/* =============================================================================
   HERO
   ========================================================================== */
.hero { padding-block: clamp(52px, 8vw, 104px) clamp(40px, 6vw, 72px); }
.hero__in { max-width: 46rem; }
.hero h1 { margin-bottom: 1.5rem; }
.hero__act { display: flex; flex-wrap: wrap; gap: .7rem; margin-top: 2rem; }
/* The three counts under the hero. Not a statistic each — a description of
   what the tool has in it, which is the only claim this page can make without
   a server behind it. */
.hero__facts {
    display: flex; flex-wrap: wrap; gap: 0 3rem;
    margin-top: 2.6rem; padding-top: 1.6rem; border-top: 1px solid var(--line);
}
.hero__fact b {
    display: block; font-size: 1.7rem; font-weight: 200; letter-spacing: -.04em;
    color: var(--ink); line-height: 1.1;
}
.hero__fact span {
    display: block; font-size: .625rem; font-weight: 700; letter-spacing: .2em;
    text-transform: uppercase; color: var(--ink-55); margin-top: .3rem;
}

/* =============================================================================
   THE CONSOLE
   -----------------------------------------------------------------------------
   The generator, its controls and its results. Everything here was a literal
   in the old file — #0f0f0f, #1a1a1a, #222, #0c0c0c, five greys inside twenty
   pixels of each other — and the whole of that is now three surfaces:

     --sur-1   the panel               a 2.5% ink wash
     --sur-2   a field inside a panel  a 4% ink wash + a real border
     --sur-3   a result row            paper, held by a hairline

   R2: on the dark ground those become white lifts, and the numbers do not
   transfer — 5% white on black reads far stronger than 5% black on white. The
   answers are in dark.css and they are not the same alphas.
   ========================================================================== */
.console {
    --sur-1: rgba(30, 38, 43, .025);
    --sur-2: rgba(30, 38, 43, .04);
    border: 1px solid var(--line); border-radius: 14px;
    background: var(--sur-1);
    overflow: hidden;
}
.console__head {
    display: flex; align-items: center; flex-wrap: wrap; gap: .8rem;
    padding: .9rem 1.2rem; border-bottom: 1px solid var(--line);
    background: var(--paper);
}
.console__title {
    font-size: .625rem; font-weight: 700; letter-spacing: .2em;
    text-transform: uppercase; color: var(--ink-55); margin: 0 auto 0 0;
    display: flex; align-items: center; gap: .55rem;
}
/* The live dot. The one place the accent is allowed to be a fill, and it is
   6 pixels across. */
.console__dot {
    width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
    flex: 0 0 auto;
}
.console__body { padding: 1.2rem; display: grid; gap: 1.15rem; }
@media (max-width: 620px) { .console__body { padding: .9rem; } }

/* -------------------------------------------------------------- the fields */
.field-row { display: flex; gap: .55rem; align-items: stretch; flex-wrap: wrap; }
.field-row > .field { flex: 1 1 15rem; min-width: 0; }
.field {
    font: inherit; font-size: .95rem; font-weight: 500;
    padding: .74rem .9rem; border-radius: 9px;
    color: var(--ink); background: var(--paper);
    /* A real border, not a hairline: an input is a box that has to announce
       itself, and --line at 12% on a white panel is an input you cannot find. */
    border: 1px solid rgba(30, 38, 43, .5);
    -webkit-appearance: none; appearance: none;
    transition: border-color .22s var(--ease), box-shadow .22s var(--ease);
}
.field::placeholder { color: var(--ink-55); font-weight: 400; }
.field:focus { outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px rgba(30, 38, 43, .07); }
.field:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.field[aria-invalid="true"] { border-color: var(--taken); }

/* The pasted list. A block field rather than a row, because what goes in it is
   several lines and a single-line input that scrolls sideways hides everything
   but the last thing typed. Resizable vertically only: horizontal resize on a
   flex child drags the panel's whole layout with it. */
.field--area {
    display: block; width: 100%; resize: vertical; min-height: 5.5rem;
    line-height: 1.55; font-size: .9rem;
    /* A list of domains is columnar data and reads as such — and a monospace
       face is also what makes a stray character in a pasted line visible. */
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
/* The button under a full-width field, pushed to the end of the row so it sits
   under the field's trailing edge rather than floating at its start. */
.field-row--end { justify-content: flex-end; margin-top: .55rem; }
/* No background fill here on purpose: the only surface tokens are --paper and
   --deep, and a hint sits on either depending on the band it is in, so a filled
   chip would be right in one place and a visible patch in the other. A hairline
   box needs no ground and is correct in both editions. */
.hint code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .92em; padding: .05em .35em; border-radius: 4px;
    border: 1px solid var(--line); color: var(--ink-77);
}

.lbl {
    display: block; font-size: .625rem; font-weight: 700; letter-spacing: .18em;
    text-transform: uppercase; color: var(--ink-55); margin-bottom: .45rem;
}
.hint { font-size: .78rem; color: var(--ink-55); margin: .4rem 0 0; }

/* ------------------------------------------------------------- the segments
   Five TLD sets and two generators. The old build had these as ten buttons
   that turned solid orange when active; here the pressed state is the ink
   itself, which is the same shape the pill and the filters use. */
.seg { display: flex; flex-wrap: wrap; gap: .4rem; }
.seg__b {
    font: inherit; font-size: .78rem; font-weight: 600; letter-spacing: -.005em;
    padding: .5rem .85rem; border-radius: 4px;
    background: transparent; color: var(--ink-77);
    border: 1px solid var(--line); cursor: pointer;
    transition: border-color .2s var(--ease), background .2s var(--ease), color .2s var(--ease);
}
.seg__b:hover { border-color: var(--ink); color: var(--ink); }
.seg__b[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.seg__b small { font-weight: 500; opacity: .62; margin-left: .35rem; }

.seg--wide { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: .4rem; }
.seg--wide .seg__b { text-align: center; border-radius: 4px; }
@media (max-width: 560px) { .seg--wide { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------- the dials */
.dials { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: 1.1rem; }
.dial[hidden] { display: none; }
.dial__top { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; }
.dial__val {
    font-size: .78rem; font-weight: 700; color: var(--accent);
    font-variant-numeric: tabular-nums;
}
input[type="range"] {
    width: 100%; margin: .35rem 0 0;
    accent-color: var(--ink);
    /* Firefox draws the track at its own height and ignores accent-color for
       the groove on some builds; the height keeps the two engines within a
       pixel of each other. */
    height: 22px;
}
input[type="range"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* -------------------------------------------------------------- the switches
   Real checkboxes with a real label, laid out as a row of chips. The old build
   had four bare checkboxes and four labels floating in a flex row, one of
   which ("Mobile") set a body class that made a desktop render as a phone. */
.switches { display: flex; flex-wrap: wrap; gap: .45rem; }
.sw {
    display: inline-flex; align-items: center; gap: .5rem;
    padding: .45rem .8rem .45rem .6rem; border-radius: 4px;
    border: 1px solid var(--line); cursor: pointer;
    font-size: .78rem; font-weight: 600; color: var(--ink-77);
    transition: border-color .2s var(--ease), color .2s var(--ease);
    user-select: none;
}
.sw:hover { border-color: var(--ink); color: var(--ink); }
.sw input { width: 15px; height: 15px; margin: 0; accent-color: var(--ink); flex: 0 0 auto; }
.sw:has(input:checked) { border-color: var(--ink); color: var(--ink); }
.sw:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ------------------------------------------------------------- the run row */
.run { display: flex; gap: .55rem; flex-wrap: wrap; align-items: center; }
.run .btn--go { flex: 1 1 16rem; font-size: .92rem; padding: .95rem 1.4rem; letter-spacing: .06em; text-transform: uppercase; }
.run__kbd { margin-left: auto; font-size: .72rem; color: var(--ink-55); }
kbd {
    font: inherit; font-size: .72rem; font-weight: 600;
    padding: .1rem .35rem; border: 1px solid var(--line); border-radius: 5px;
    background: var(--paper); color: var(--ink-77);
}

/* =============================================================================
   RESULTS
   ========================================================================== */
.out {
    border-top: 1px solid var(--line);
    background: var(--paper);
    padding: 1.2rem;
    min-height: 22rem;
}
@media (max-width: 620px) { .out { padding: .9rem; } }

.out__bar {
    display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;
    margin-bottom: .9rem;
}
.out__n {
    font-size: .625rem; font-weight: 700; letter-spacing: .18em;
    text-transform: uppercase; color: var(--ink-55); margin: 0 auto 0 0;
    font-variant-numeric: tabular-nums;
}
.out__n b { color: var(--ink); }

/* The welcome panel: what the tool is, before it has been asked to do
   anything. It is the only long-form copy inside the console. */
.welcome { max-width: 60ch; }
.welcome h3 { font-size: 1.28rem; font-weight: 300; letter-spacing: -.03em; margin: 0 0 .8rem; }
.welcome p { margin: 0 0 .9rem; font-size: .92rem; }
.welcome ul { margin: 0 0 1rem; padding-left: 1.1rem; font-size: .92rem; }
.welcome li { margin-bottom: .35rem; }
.welcome li::marker { color: var(--accent); }
.welcome strong { color: var(--ink); font-weight: 600; }

/* -------------------------------------------------------------- a result row
   The domain is the largest type in the row and everything else is a label
   beside it. It was 1.28rem at 600 on a #1a1a1a slab with a 4px orange bar
   down the left; here the row is paper on paper, held by a hairline, and the
   status is what carries the colour. */
.dom {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center; gap: .5rem 1rem;
    padding: .85rem 1rem;
    border: 1px solid var(--line); border-radius: 10px;
    background: var(--paper);
    transition: border-color .18s var(--ease);
}
.dom + .dom { margin-top: .5rem; }
.dom:hover { border-color: rgba(30, 38, 43, .28); }
.dom[data-state="free"]    { border-left: 3px solid var(--free); }
.dom[data-state="taken"]   { border-left: 3px solid var(--taken); }
.dom[data-state="unknown"] { border-left: 3px solid var(--unsure); }
.dom[data-state="norda"]   { border-left: 3px solid var(--line); }

.dom__name {
    font-size: 1.16rem; font-weight: 600; letter-spacing: -.025em;
    color: var(--ink); overflow-wrap: anywhere; min-width: 0;
    display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
}
.dom__tld { color: var(--ink-55); font-weight: 500; }
.dom__acts { display: flex; gap: .35rem; flex-wrap: wrap; justify-content: flex-end; }

/* On a phone the two-column row fails badly rather than gracefully: the acts
   column resolves to its max-content (~230px of chip and buttons), the 1fr
   name column is left ~20px, and overflow-wrap:anywhere — right for genuinely
   long names — obliges by setting the name vertically, two letters a line.
   One column: the name owns its row and the actions sit under it. */
@media (max-width: 560px) {
    .dom { grid-template-columns: 1fr; }
    .dom__acts { justify-content: flex-start; }
}
.dom__detail { grid-column: 1 / -1; }
.dom__detail:empty { display: none; }

/* The icon buttons on a row: WHOIS, star, copy. Square, hairline, a glyph
   each — at three per row and twenty-five rows, anything with a word in it
   made the column wider than the domains. */
.ib {
    width: 32px; height: 32px; padding: 0; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: 1px solid var(--line); border-radius: 8px;
    color: var(--ink-55); cursor: pointer;
    transition: border-color .2s var(--ease), color .2s var(--ease), background .2s var(--ease);
}
.ib:hover { border-color: var(--ink); color: var(--ink); }
.ib[disabled] { opacity: .4; cursor: default; }
.ib svg { width: 14px; height: 14px; display: block; }
.ib[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); background: rgba(194, 65, 12, .06); }
/* The busy state. A spinner would be a fourth moving thing on a page that is
   already listing twenty-five rows; a pulse on the button that was pressed is
   enough and it stays where the eye already is. */
.ib[data-busy="1"] { animation: pulse 1.1s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .38; } }
@media (prefers-reduced-motion: reduce) { .ib[data-busy="1"] { animation: none; opacity: .55; } }

/* ------------------------------------------------------------- status chips
   Four states, and the fourth is the one the old build did not have. It
   reported AVAILABLE whenever a query failed — a timeout, a CORS refusal, a
   registry with no RDAP at all — which is the single most expensive thing a
   tool like this can get wrong, because the answer looks like the good news. */
.st {
    display: inline-flex; align-items: center; gap: .4rem;
    font-size: .625rem; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
    padding: .28rem .6rem; border-radius: 4px; white-space: nowrap;
    border: 1px solid currentColor;
}
.st::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.st--free    { color: var(--free);   background: var(--free-wash); }
.st--taken   { color: var(--taken);  background: var(--taken-wash); }
.st--unknown { color: var(--unsure); background: var(--unsure-wash); }
.st--norda   { color: var(--ink-55); background: transparent; }
.st--busy    { color: var(--ink-55); background: transparent; }
/* An ending that publishes no RDAP, where DNS says the name is not delegated.
   Deliberately NOT the green of --free: it is a narrowing, not a yes, and a row
   that looks identical to a confirmed availability is a row that will be read
   as one. The undetermined amber, filled, so it reads as a finding rather than
   as the blank that plain --norda is. */
.st--maybe   { color: var(--unsure); background: var(--unsure-wash); }

/* ---------------------------------------------------------- the detail slab
   What RDAP actually said. A definition list, because that is what it is. */
.rec {
    margin-top: .7rem; padding: .8rem .9rem;
    border: 1px solid var(--line); border-radius: 9px;
    background: rgba(30, 38, 43, .022);
    font-size: .84rem;
}
.rec dl { display: grid; grid-template-columns: auto 1fr; gap: .2rem .9rem; margin: 0; }
.rec dt {
    font-size: .58rem; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
    color: var(--ink-55); padding-top: .22rem;
}
.rec dd { margin: 0; color: var(--ink-77); overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.rec dd b { color: var(--ink); font-weight: 600; }
.rec__note { margin: .6rem 0 0; font-size: .78rem; color: var(--ink-55); }
@media (max-width: 480px) { .rec dl { grid-template-columns: 1fr; gap: 0 0; } .rec dt { padding-top: .5rem; } }

/* ------------------------------------------------------------- the buy row
   Five registrars. The old build gave each one its brand colour as a solid
   fill: #00cc66 with black type, #0033a0 with white, #f26522 with white at
   2.9:1. Five brand fills in a row is five accents on a page that has one, and
   half of them failed contrast in either edition.

   They are ghost buttons now, all in the ink, each carrying its brand as a
   6px dot. The colour still identifies the registrar; it is no longer trying
   to be a background for text. This is R7's "keep the raw value for fills" —
   the raw value survives, on the only surface small enough to hold it. */
.buys { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .75rem; }
.buy {
    display: inline-flex; align-items: center; gap: .45rem;
    font-size: .74rem; font-weight: 600; letter-spacing: -.005em;
    padding: .45rem .75rem; border-radius: 8px;
    border: 1px solid var(--line); color: var(--ink-77);
    text-decoration: none; white-space: nowrap;
    transition: border-color .2s var(--ease), color .2s var(--ease);
}
.buy:hover { border-color: var(--ink); color: var(--ink); }
.buy__dot { width: 6px; height: 6px; border-radius: 50%; flex: 0 0 auto; }
.buy::after {
    content: '↗'; font-size: .68em; color: var(--ink-55); margin-left: .05rem;
}

/* ------------------------------------------------------------ social links */
.socials { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .6rem; }
.social {
    display: inline-flex; align-items: center; gap: .35rem;
    font-size: .74rem; font-weight: 600;
    padding: .38rem .7rem; border-radius: 8px;
    border: 1px solid var(--line); color: var(--info);
    text-decoration: none; white-space: nowrap;
}
.social:hover { border-color: currentColor; }

/* The announcement cards live in their own sheet — assets/css/toast.css, the
   LAB DMT system — because they are a component this page borrows rather than
   one it owns, and keeping them separate is what lets the next page take them
   without taking the console with them. The one rule this sheet has about them
   is where they sit in the stack: above the nav (60) and the menu (200). */

/* The TOAST:ON/OFF switch in the console head. The engine owns its label and
   its state; this is only what it looks like sitting in the bar. */
.tbtn {
    font: inherit; font-size: .58rem; font-weight: 700; letter-spacing: .14em;
    padding: .34rem .6rem; border-radius: 4px;
    background: transparent; color: var(--ink-55);
    border: 1px solid var(--line); cursor: pointer;
    transition: border-color .2s var(--ease), color .2s var(--ease);
}
.tbtn:hover { border-color: var(--ink); color: var(--ink); }
.tbtn.on { color: var(--accent); border-color: var(--accent); }

/* --------------------------------------------------------------- compact
   What replaces the old build's "Mobile" checkbox — which was on by default
   and made a 27-inch display render at phone padding, because it was a
   preference standing in for a media query.

   Width is the media query's job and it is done above. This is the other
   thing that checkbox was half-doing and never said: density. It is a real
   preference — some people want twenty-five rows on one screen — so it is
   off by default, remembered, and it changes nothing but spacing. */
.is-compact .out { padding: .7rem; }
.is-compact .dom { padding: .5rem .7rem; }
.is-compact .dom + .dom { margin-top: .3rem; }
.is-compact .dom__name { font-size: 1rem; }
.is-compact .console__body { gap: .8rem; padding: .9rem; }
.is-compact .rec { padding: .6rem .7rem; font-size: .8rem; }

/* =============================================================================
   THE REGISTER — the TLD sets, as a table of what is in each one
   ========================================================================== */
.reg { border-top: 1px solid var(--line); }
.reg__row {
    display: grid; grid-template-columns: 13rem 1fr auto;
    gap: .4rem 1.6rem; align-items: baseline;
    padding: 1.1rem 0; border-bottom: 1px solid var(--line);
}
@media (max-width: 760px) { .reg__row { grid-template-columns: 1fr; } }
.reg__k { font-size: 1.05rem; font-weight: 600; letter-spacing: -.025em; color: var(--ink); }
.reg__v { font-size: .88rem; color: var(--ink-55); overflow-wrap: anywhere; }
.reg__n {
    font-size: .625rem; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
    color: var(--ink-55); white-space: nowrap; font-variant-numeric: tabular-nums;
}

/* =============================================================================
   POSITIONS — the three-up grid used by the "what a check tells you" band
   ========================================================================== */
.three { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 2.4rem; }
.pos__n {
    font-size: .625rem; font-weight: 700; letter-spacing: .2em;
    color: var(--accent); margin-bottom: .8rem;
}
.pos h3 { font-size: 1.28rem; font-weight: 300; letter-spacing: -.03em; margin-bottom: .6rem; }
.pos p { margin: 0; font-size: .95rem; }

/* =============================================================================
   FOOTER
   ========================================================================== */
.foot { border-top: 1px solid var(--line-dark); background: var(--deep); color: rgba(255, 255, 255, .5); }
.foot__in { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 2rem; padding-block: 2.2rem; }
.foot__in p { margin: 0; font-size: .78rem; }
.foot__links { display: flex; flex-wrap: wrap; gap: 1.4rem; margin-left: auto; }
.foot__links a { font-size: .78rem; text-decoration: none; color: rgba(255, 255, 255, .5); }
.foot__links a:hover { color: #fff; }

/* =============================================================================
   REVEAL
   -----------------------------------------------------------------------------
   Held to a short rise with no scale and no stagger beyond a beat.

   The hidden state is gated on html.js — the class the inline <head> latch
   sets before anything paints. Only a browser definitely running our script
   gets an element hidden pending that script's reveal; everyone else gets the
   content. Without this, the h1 and the whole console would be opacity:0 until
   the observer ran, so any throw before that point serves an empty page rather
   than an unanimated one.
   ========================================================================== */
html.js .rise { opacity: 0; transform: translateY(14px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
html.js .rise.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
    html.js .rise { opacity: 1; transform: none; transition: none; }
    .btn, .dom, .seg__b, .ib, .buy { transition: none; }
}

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }

/* Read, not seen. The pill's lit segment is a span rather than a link, and a
   span carrying only an aria-label is announced by nothing — so it carries its
   words as real text and hides them here instead. */
.vh {
    position: absolute; width: 1px; height: 1px; margin: -1px;
    padding: 0; border: 0; overflow: hidden; white-space: nowrap;
    clip: rect(0 0 0 0); clip-path: inset(50%);
}

/* The skip link. background:var(--ink) + color:#fff, which the dark edition
   has to answer or it is white on white — invisible to every check that only
   looks at what is on screen, and the very first thing a keyboard user
   reaches. */
.skip {
    position: absolute; left: -9999px; top: 0; z-index: 400;
    background: var(--ink); color: #fff; padding: .8rem 1.2rem; text-decoration: none;
}
.skip:focus { left: 0; }

/* Print. The console is a screen tool and its controls mean nothing on paper;
   what a printed page is for is the list of names and their status. */
@media print {
    .nav, .menu, .console__body, .out__bar .btn, .dom__acts, .foot, .hero__act, .toast { display: none !important; }
    body { font-size: 12px; }
    .band { padding-block: 1rem; }
    .dom { break-inside: avoid; border-left-width: 3px; }
}

/* =============================================================================
   NETWORK LABS — the instrument outputs
   -----------------------------------------------------------------------------
   Added for labs.llc/labluxa/. Everything below reads the same tokens the rest
   of the sheet does (--ink, --paper, --line, --free/--taken/--unsure), so the
   dark edition inherits it through dark.css with no second copy. The output
   panels are set in the mono face the rest of the console diagnostics use.
   ========================================================================== */
.probe-out, .short-out, .pw-out {
    margin-top: 1rem;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--paper);
    padding: 1rem 1.15rem;
}
.probe-out {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .82rem;
    line-height: 1.65;
    max-height: 60vh;
    overflow-y: auto;
}
.probe-out > div { margin: .18rem 0; }
.probe-label {
    color: var(--ink-55);
    margin-top: 1rem !important;
    font-size: .74rem;
    letter-spacing: .01em;
}
.probe-note { color: var(--ink-55); font-style: italic; }
.probe-card {
    margin: .5rem 0 !important;
    padding: .7rem .85rem;
    background: var(--tint);
    border-left: 3px solid var(--line);
    border-radius: 8px;
}
.probe-card.good { border-left-color: var(--free); }
.probe-hop {
    padding: .35rem .6rem;
    background: var(--tint);
    border-left: 2px solid var(--line);
    border-radius: 6px;
}
.probe-continent {
    margin-top: 1.1rem !important;
    padding-bottom: .35rem;
    border-bottom: 1px solid var(--line);
    font-weight: 600;
    color: var(--ink);
}
.probe-site {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    align-items: baseline;
    padding: .2rem 0;
}
.probe-site b { font-weight: 600; }
.probe-ip { color: var(--ink-55); font-size: .74rem; }
.probe-site .good, .probe-site .bad { margin-left: auto; }
.probe-verdict, .probe-done {
    margin-top: 1.1rem !important;
    padding: .85rem 1rem;
    background: var(--tint);
    border-left: 3px solid var(--accent);
    border-radius: 8px;
}
.probe-rating { font-size: 1.15rem; font-weight: 700; display: inline-block; margin-top: .3rem; }

.good { color: var(--free); font-weight: 600; }
.warn { color: var(--unsure); font-weight: 600; }
.bad  { color: var(--taken); font-weight: 600; }

/* Shortener + password results share one card shape. */
.short-out__link, .pw-out__word {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--ink);
    word-break: break-all;
    margin: 0 0 .8rem 0;
}
.pw-out__word { color: var(--accent); }
.short-out .field-row, .pw-out .field-row { margin-bottom: .6rem; }

@media (max-width: 560px) {
    .probe-out { font-size: .78rem; }
    .short-out__link, .pw-out__word { font-size: 1.05rem; }
}

/* The per-instrument output toolbar (Download PDF). Shown by app.js once a run
   has produced something worth exporting. */
.out-tools {
    display: flex;
    gap: .5rem;
    flex-wrap: wrap;
    margin-top: 1rem;
}

/* =============================================================================
   SEARCH — the box's own furniture
   ========================================================================== */
.sr-quick {
    margin: .4rem 0 .6rem;
    padding: .75rem .95rem;
    background: var(--tint);
    border-left: 3px solid var(--accent);
    border-radius: 8px;
    font-size: .92rem;
}
.sr-snip {
    flex-basis: 100%;
    font-size: .78rem; color: var(--ink-55); line-height: 1.5;
    font-family: var(--font, inherit);
}
.sr-img-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: .5rem;
    margin: .5rem 0;
}
.sr-img {
    display: block; aspect-ratio: 4 / 3; overflow: hidden;
    border: 1px solid var(--line); border-radius: 8px; background: var(--tint);
}
.sr-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sr-img:hover { border-color: var(--accent); }
.sr-launch { display: flex; flex-wrap: wrap; gap: .45rem; }
.sr-history { display: flex; flex-wrap: wrap; gap: .4rem; }
.sr-chip { border-radius: 4px; }
.sr-chip--x { color: var(--ink-55); }
.probe-out .probe-site b a { color: var(--ink); text-decoration: none; }
.probe-out .probe-site b a:hover { text-decoration: underline; }
@media (max-width: 560px) {
    .sr-img-grid { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
}

/* ------------------------------------------------------------- a row that acts
   .menu__row was written for <a>. A <button> wearing the same class arrives
   with the user agent's own 2px outset border, its buttonface background, its
   13px Arial and — because .menu__row is a flex container — a width that
   shrinks to its own text. Eight such rows of differing lengths read as a
   staircase of framed grey boxes beside a clean list of links, which is exactly
   what they were.

   Everything here is a reset, not a style. The point is that a button in this
   menu is indistinguishable from a link in it. The bottom rule is re-declared
   because `border: 0` above would take it with the rest, and the existing
   `.menu__row:last-child` still wins on specificity, so the last row of a
   section stays clean. */
button.menu__row {
    width: 100%;
    box-sizing: border-box;
    -webkit-appearance: none;
    appearance: none;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--line-soft);
    border-radius: 0;
    font: inherit;
    text-align: left;
    cursor: pointer;
}


/* ------------------------------------------------------- the shelf as a door
   Every drawer shelf is a room now, and the room is a page. The heading is the
   link to it: same size, same tracking, same colour as a plain heading, with an
   arrow that only moves on hover — a heading that shouted would compete with
   the tiles under it, which are the thing somebody came to the drawer for. */
.menu__h--door { padding: 0; }
.menu__h--door a {
    display: inline-flex; align-items: center; gap: .4em;
    color: inherit; text-decoration: none;
}
.menu__h--door a i { font-style: normal; opacity: 0; transform: translateX(-3px); }
.menu__h--door a:hover, .menu__h--door a:focus-visible { color: var(--accent); }
.menu__h--door a:hover i, .menu__h--door a:focus-visible i {
    opacity: 1; transform: none;
}
.menu__h--door a i { transition: opacity .16s ease, transform .16s ease; }
.menu__h--door a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
@media (prefers-reduced-motion: reduce) {
    .menu__h--door a i { transition: none; }
}

/* THE CORRECTION, offered under the header rather than applied to the box. */
.sr-didyoumean { margin: .35rem 0 .2rem; font-size: .86rem; color: var(--ink-70, var(--muted)); }
/* Styled like a history chip and deliberately NOT one: .sr-chip carries a
   click delegate that re-runs the search from the chip's own data-q. */
.sr-sug {
    font: inherit; font-weight: 700; cursor: pointer;
    background: none; border: 0; padding: 0;
    color: var(--accent); text-decoration: underline; text-underline-offset: 2px;
}
.sr-sug:hover { color: var(--ink); }


/* =============================================================================
   SEARCH CONTROLS - Rams/Braun pass, matching laband and composer
   -----------------------------------------------------------------------------
   Three problems this fixes, all measured on the live page:

   1. TEN LENSES IN A THREE-COLUMN GRID. 3+3+3+1 orphaned "Art" on a row of its
      own. Ten divides by five and by two, never by three, so the grid is now 5x2
      on desktop and 2x5 on a phone - symmetric at both ends and never a widow.
   2. TWO RADII AND TWO HEIGHTS IN ONE CARD. .seg__b was a 999px pill and
      .seg--wide .seg__b overrode it to 9px. Now every control in the card is
      one shape (4px), one height (34px) and one label recipe.
   3. THE RESULTS PANEL WAS FIXED AT 60vh with no way to change it, so a query
      returning six feeds scrolled inside a short window. Now a three-segment
      Height switch: Short 40vh, Tall 78vh, Full uncapped.

   #main so one rule owns both editions - dark.css links after this file and
   out-orders a bare class. Hairlines mix ink with TRANSPARENT, never with
   var(--paper): a .band--deep section repoints --ink and leaves --paper white,
   and a two-token mix resolves white-on-white there.
   ========================================================================== */

#main .seg--wide {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: .34rem;
}

/* ---------------------------------------------------------------------------
   ONE CONTROL RECIPE. Braun is flat: a 4px corner, a hairline, a 10px/600/.12em
   uppercase label and ONE height across every control in the card - the ten
   lenses, the two switches and the three height segments all measure the same.
   Selection is a solid ink fill, the single loudest thing on the panel. No
   999px pills anywhere: a rounded pill is a different design language and it
   read as one against the rest of the console.
   --------------------------------------------------------------------------- */
#main .seg__b,
#main .opts .sw {
    min-height: 34px;
    padding: 0 .7rem;
    font-family: inherit;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
    line-height: 1;
    border-radius: 4px;
    border: 1px solid color-mix(in srgb, var(--ink) 24%, transparent);
    background: transparent;
    color: var(--ink);
    display: inline-flex; align-items: center; justify-content: center;
    gap: .5rem;
    cursor: pointer;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
}
#main .seg__b:hover,
#main .opts .sw:hover { border-color: color-mix(in srgb, var(--ink) 55%, transparent); }
#main .seg__b[aria-pressed="true"] {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper);
}
#main .seg__b small {
    font-size: 9px; font-weight: 600; letter-spacing: .1em;
    opacity: .6; margin-left: .4rem;
}
#main .seg__b:focus-visible,
#main .opts .sw:focus-within {
    outline: 2px solid color-mix(in srgb, var(--ink) 70%, transparent);
    outline-offset: 2px;
}

/* the switches are labels, so the box is the control - square it and size it
   to the 13px Braun tick rather than the browser's default 16px chrome. */
#main .opts .sw { justify-content: flex-start; }
#main .opts .sw input[type="checkbox"] {
    appearance: none; -webkit-appearance: none;
    width: 13px; height: 13px; margin: 0; flex: 0 0 auto;
    border: 1px solid color-mix(in srgb, var(--ink) 45%, transparent);
    border-radius: 2px; background: transparent; cursor: pointer;
    display: inline-grid; place-content: center;
}
#main .opts .sw input[type="checkbox"]::after {
    content: ""; width: 7px; height: 4px;
    border-left: 1.5px solid var(--paper); border-bottom: 1.5px solid var(--paper);
    transform: rotate(-45deg) translate(0, -1px); opacity: 0;
}
#main .opts .sw input[type="checkbox"]:checked {
    background: var(--ink); border-color: var(--ink);
}
#main .opts .sw input[type="checkbox"]:checked::after { opacity: 1; }

/* the options row: switches left, height right, one line where there is room */
#main .opts {
    display: flex; flex-wrap: wrap; align-items: center;
    justify-content: space-between; gap: .5rem .9rem;
    margin-top: .9rem;
}
#main .opts .switches { display: flex; flex-wrap: wrap; gap: .34rem; margin: 0; }
#main .opts__h { display: flex; align-items: center; gap: .55rem; }
#main .opts__h .lbl {
    margin: 0; font-size: 10px; font-weight: 600;
    letter-spacing: .12em; text-transform: uppercase; opacity: .6;
}
#main .seg--h { display: inline-flex; gap: .34rem; }

/* the results panel, driven by the Height switch */
#main .probe-out { max-height: 78vh; }
#main .probe-out[data-h="short"] { max-height: 40vh; }
#main .probe-out[data-h="tall"]  { max-height: 78vh; }
#main .probe-out[data-h="full"]  { max-height: none; overflow-y: visible; }

/* phone: two columns of five, and full-width controls that stay tappable */
@media (max-width: 640px) {
    #main .seg--wide { grid-template-columns: repeat(2, 1fr); gap: .34rem; }
    #main .seg__b, #main .opts .sw { min-height: 40px; }
    #main .opts .switches, #main .opts__h { width: 100%; }
    #main .opts .sw { flex: 1 1 0; }
    #main .opts { justify-content: flex-start; }
    #main .opts__h { width: 100%; justify-content: space-between; }
    #main .seg--h { flex: 1 1 auto; }
    #main .seg--h .seg__b { flex: 1 1 0; }
    #main .probe-out { max-height: 68vh; }
    #main .probe-out[data-h="short"] { max-height: 45vh; }
}
@media (min-width: 641px) and (max-width: 900px) {
    #main .seg--wide { grid-template-columns: repeat(5, 1fr); gap: .3rem; }
    #main .seg__b { padding: 0 .5rem; }   /* label recipe holds at 10px */
}


/* ------------------------------------------------------------------- the wire
   A numbered list, not cards: twelve headlines read faster in one column with a
   rank than in a grid a reader has to scan. The number is tabular so the column
   does not shift between 01 and 12. Rules are hairlines mixed with transparent,
   for the reason set out above. */
#main .wire__head {
    display: flex; flex-wrap: wrap; align-items: baseline;
    justify-content: space-between; gap: .5rem 1rem;
}
#main .wire__ctl { display: flex; align-items: center; gap: .6rem; }
#main .wire__stamp {
    font-size: .7rem; font-weight: 600; letter-spacing: .06em;
    text-transform: uppercase; color: var(--ink-55);
    font-variant-numeric: tabular-nums;
}
#main #wire-refresh[aria-busy="true"] { opacity: .55; pointer-events: none; }

#main .wire { list-style: none; margin: 1.1rem 0 0; padding: 0; }
#main .wire__i {
    display: grid;
    grid-template-columns: 2.1rem minmax(0, 1fr) auto;
    align-items: baseline; gap: .1rem .7rem;
    padding: .62rem 0;
    border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
}
#main .wire__i:first-child { border-top: 0; }
#main .wire__n {
    font-size: .72rem; font-weight: 600; color: var(--ink-55);
    font-variant-numeric: tabular-nums;
}
#main .wire__t {
    font-size: .95rem; line-height: 1.4; font-weight: 500;
    color: var(--ink); text-decoration: none;
}
#main .wire__t:hover { text-decoration: underline; text-underline-offset: 2px; }
#main .wire__m {
    font-size: .72rem; color: var(--ink-55); white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
#main .wire__i--bad,
#main .wire > li:only-child:not(:has(.wire__t)) {
    grid-template-columns: 1fr; color: var(--ink-55); font-size: .85rem;
}
#main .wire__note { margin-top: 1rem; font-size: .78rem; line-height: 1.55; color: var(--ink-55); }

/* Phone: the source-and-time drops under the headline rather than squeezing it
   into a column too narrow to read. */
@media (max-width: 640px) {
    #main .wire__i { grid-template-columns: 1.8rem minmax(0, 1fr); }
    #main .wire__m { grid-column: 2; white-space: normal; }
    #main .wire__t { font-size: .92rem; }
    #main .wire__head { gap: .4rem; }
    #main .wire__ctl { width: 100%; justify-content: space-between; }
}


/* ------------------------------------------------- tools inside the query field
   A dice and a clear, sitting in the field rather than beside it, so the row does
   not grow two more buttons competing with Search for the eye.

   The native control is suppressed: type="search" draws its own clear cross in
   WebKit, and two crosses a few pixels apart is worse than none. One height, one
   hairline, the same 999px choice shape the segments use.

   Glyphs are DRAWN. A text multiplication sign renders at a different width in
   every face and a text die resolves to a colour emoji on several platforms -
   either one makes the pair jump as they swap in and out. */
#main .field-wrap { position: relative; display: block; flex: 1 1 15rem; min-width: 0; }
#main .field-wrap > .field { width: 100%; }
#main .field--has-tools { padding-right: 4.6rem; }
#main .field--has-tools::-webkit-search-cancel-button,
#main .field--has-tools::-webkit-search-decoration { -webkit-appearance: none; display: none; }

#main .field-tools {
    position: absolute; top: 50%; right: .45rem; transform: translateY(-50%);
    display: flex; align-items: center; gap: .25rem;
}
#main .fbtn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; padding: 0;
    border-radius: 4px;
    border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
    background: transparent; color: var(--ink-55);
    cursor: pointer; line-height: 0;
    transition: color .18s var(--ease), border-color .18s var(--ease), background-color .18s var(--ease);
}
#main .fbtn:hover { color: var(--ink); border-color: var(--ink); }
#main .fbtn:active { background: color-mix(in srgb, var(--ink) 8%, transparent); }
#main .fbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#main .fbtn[hidden] { display: none; }
#main .fbtn--rolling { animation: fbtn-roll .5s var(--ease); }
@keyframes fbtn-roll { from { transform: rotate(0); } to { transform: rotate(180deg); } }
@media (prefers-reduced-motion: reduce) { #main .fbtn--rolling { animation: none; } }

/* Coarse pointers get a real target without the field growing taller. */
@media (pointer: coarse) {
    #main .fbtn { width: 34px; height: 34px; }
    #main .field--has-tools { padding-right: 5.4rem; }
}


/* ------------------------------------------------------- the first-visit pulse
   A new visitor sees a box and a lot of prose. This says "start here" without a
   banner, a tooltip or a modal.

   Rules it keeps:
   - FIRST VISIT ONLY, and it stops the instant the box is touched. A pulse that
     runs forever is an animation; one that stops when it is understood is a hint.
   - It rings, it does not blink. Opacity flashing on a form control reads as an
     error state; a soft expanding ring reads as an invitation.
   - Three cycles, then still. Anything that keeps moving while you are trying to
     type is an obstacle.
   - It never touches the field's own border colour, so focus and invalid states
     stay legible while it runs.
   - prefers-reduced-motion removes the motion and leaves one static ring, which
     still marks the spot.

   The green is defined for both editions here rather than in dark.css, so one
   value change moves both. */
#main .field-wrap { --pulse: 34, 160, 100; }
:root[data-dark] #main .field-wrap { --pulse: 74, 214, 146; }

#main .field-wrap--invite > .field {
    animation: q-invite 2.1s var(--ease) 3;
}
@keyframes q-invite {
    0%   { box-shadow: 0 0 0 0   rgba(var(--pulse), .00); }
    18%  { box-shadow: 0 0 0 4px rgba(var(--pulse), .26); }
    60%  { box-shadow: 0 0 0 9px rgba(var(--pulse), .00); }
    100% { box-shadow: 0 0 0 0   rgba(var(--pulse), .00); }
}
/* the dice is the other way in, so it gets a quieter tint for the same window */
#main .field-wrap--invite #q-dice {
    border-color: rgba(var(--pulse), .55);
    color: rgb(var(--pulse));
}
@media (prefers-reduced-motion: reduce) {
    #main .field-wrap--invite > .field {
        animation: none;
        box-shadow: 0 0 0 3px rgba(var(--pulse), .20);
    }
}


/* =============================================================================
   ACTIONS - the Braun pass, matching laband and composer
   -----------------------------------------------------------------------------
   The estate's rule is one shape per job: 999px says CHOOSE (the lens segments,
   the height switch), 4px says DO (Search, Stop, Download PDF, Clear). Before
   this the console mixed 8px buttons with 999px segments and a 9px field, so
   three shapes argued in one card and nothing read as a set.

   Also removed: `transform: translateY(-1px)` on hover. A control that lifts when
   you approach it is the opposite of this idiom - the feedback belongs in the
   fill, not in the geometry, and a moving target is worse on a touch screen where
   the finger is already committed.

   One height (34px) and one label recipe (10px / 600 / .12em, uppercase) across
   every action in the console, so Search, Stop, Download PDF and Clear are
   visibly the same kind of thing. The hero's two calls to action keep their
   reading size - they are prose-scale invitations, not panel controls - but take
   the same 4px corner so the whole page still agrees about what a button is.
   ========================================================================== */

/* every action, everywhere on this property: square corner, no lift */
#main .btn { border-radius: 4px; }
#main .btn:hover { transform: none; }
#main .btn:active { transform: none; }

/* the console's controls: one height, one label recipe */
#main .console .btn {
    min-height: 34px;
    padding: 0 .9rem;
    font-size: .625rem;              /* 10px */
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
    border-radius: 4px;
}
#main .console .btn--sm { font-size: .625rem; padding: 0 .8rem; min-height: 34px; }

/* EXCEPT the recent-query chips. Those are not labels, they are the visitor's
   own words played back, and uppercasing them misreports what was typed - a
   search for "koblence" is not a search for "KOBLENCE". They keep the action
   height and corner, and lose the label recipe. */
#main .console .sr-history .btn,
#main .console .sr-chip {
    text-transform: none;
    letter-spacing: normal;
    font-size: .72rem;
    font-weight: 500;
    border-radius: 4px;              /* squared like everything else in the card */
}

/* the field squares off to match, and its inner tools with it */
#main .field { border-radius: 4px; }
#main .fbtn { border-radius: 4px; width: 26px; height: 26px; }
@media (pointer: coarse) { #main .fbtn { width: 32px; height: 32px; } }

/* the field row shares the action height so the box and its buttons align */
#main .field-row { align-items: stretch; }
#main .field-row > .field-wrap > .field { min-height: 42px; }
#main .field-row > .btn { min-height: 42px; }

/* No pills. Braun does not round a control to a lozenge - the corner is 4px on
   the lens buttons, the switches, the height segments, the recall chips and the
   Search action alike, and SELECTION (a solid ink fill) is what separates a
   chosen control from an unchosen one. An earlier pass here encoded a
   999px-means-choice rule; on this console it just put two design languages in
   one card. */

@media (max-width: 640px) {
    #main .field-row > .btn { flex: 1 1 0; }
    #main .console .btn { padding: 0 .7rem; }
}

/* =============================================================================
   THE THREE PRESENTATION SWITCHES
   -----------------------------------------------------------------------------
   Dense, No repeats and Hide quiet feeds. Two of the three are pure CSS acting
   on classes the runner puts on the output panel, which is why they redraw the
   results already on screen instead of asking seventeen feeds the same question
   again. Every rule is scoped to #main so it out-orders dark.css.
   ============================================================================= */

/* DENSE — the snippet is what costs the height, so it goes first. */
#main .probe-out.sr-dense .probe-site { margin: .1rem 0; line-height: 1.3; }
#main .probe-out.sr-dense .sr-snip { display: none; }
#main .probe-out.sr-dense .probe-continent { margin: .5rem 0 .2rem; }
#main .probe-out.sr-dense .sr-img-grid { gap: .25rem; }

/* HIDE QUIET FEEDS — folded, never deleted: unticking brings it back with no
   second request. [hidden] is not used here because the estate sets
   [hidden]{display:none!important} and that would beat the untick. */
#main .probe-out.sr-hushed .probe-continent.sr-quiet { display: none; }

/* The switch row now carries five controls and has to wrap like a paragraph
   rather than stretch each one, or a two-word label and a three-word label end
   up different widths on the same line. */
#main .opts .switches { flex: 1 1 auto; }
@media (max-width: 640px) { #main .opts .sw { flex: 0 1 auto; } }

/* the standalone's per-feed retry pill */
.sr-retry { font: inherit; font-size: .72rem; font-weight: 600; letter-spacing: .04em; padding: .15rem .6rem; border-radius: 999px;
  border: 1px solid var(--line); background: transparent; color: var(--ink-77); cursor: pointer; margin-left: .4rem; vertical-align: middle; }
.sr-retry:hover { border-color: var(--ink); color: var(--ink); }
.sr-retry:disabled { opacity: .5; cursor: default; }
