/* =============================================================================
   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 ė.tv 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 ė.tv 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('/assets/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('/assets/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;
    --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 ė.tv 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 ė.tv, 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; }
    .field { font-size: 16px; }
}
.menu__clear {
    /* The root sheet and the sub-directory copies had drifted apart — 1.75rem
       against 2rem, a round button against a 6px one — so the clear sat in a
       different place depending on which page you opened the menu from. One
       geometry, stated here, and it is measured off the FIELD's own inset
       rather than the panel's padding so it cannot drift again. */
    position: absolute; right: 1.9rem; 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: 50%;
    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: 999px;
    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: 9px; }
@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: 999px;
    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: 999px; 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: 999px;
    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; }
}

/* ------------------------------------------------------------- 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; }
}

/* Same argument as .menu__q above: under 16px, iOS Safari zooms the focused
   field and carries the layout off-screen. Matched on the pointer, not the
   width, because a narrow desktop window does not zoom. Last in the sheet on
   purpose: every `.field` rule above is the same 0,1,0 specificity, so the
   one that wins is the one that comes last. */
@media (hover: none) and (pointer: coarse) {
    .field { font-size: 16px; }
}

/* ---------------------------------------------------------------------------
   THE CLEAR KEY — the mark you see is now the key you press  (v468)
   ---------------------------------------------------------------------------
   Two things were wrong and they were the same thing.

   `.menu__search svg` was written for ONE svg, the magnifier, and given the
   magnifier's geometry: position absolute, left 2.05rem, pointer-events none.
   But it is a descendant selector, and there is a second svg in that strip —
   the X inside the clear button. It was taking the magnifier's rule too. So
   the X was drawn 2.05rem from its BUTTON's left edge (the button is itself
   positioned, so it became the containing block), which put the mark about
   three pixels PAST the field's right border, sitting in the gutter.

   The button never moved: it is 22px wide, inset 1.9rem, comfortably inside
   the field. Which is why pressing the X did nothing at all. The mark a reader
   could see was ten pixels right of the control, and it carried
   pointer-events: none, so the click fell straight through it to the strip
   behind. A control that is in the wrong place AND cannot be pressed reads as
   a rendering fault; it was one selector reaching one element too far.

   The glyph is put back in its button's flow — the button already centres it —
   and the tap target is grown to 40px underneath, without moving a pixel of
   the drawing.
   ------------------------------------------------------------------------ */
.menu__clear svg {
    position: static; left: auto; top: auto; right: auto; transform: none;
    width: 10px; height: 10px;
}
.menu__clear::after {
    content: ''; position: absolute;
    top: -9px; right: -8px; bottom: -9px; left: -9px;
}

/* =============================================================================
   THE WHOIS VIP — the key in the bar, the ribbon on the hero, the row link
   -----------------------------------------------------------------------------
   The WHOIS engine at whois/ is the second tool on this site, and the brief
   was that it be found from the front door without being looked for: a VIP key
   in the header, a ribbon at the top of the hero, a row in the menu, and a way
   into the full report from every looked-up name. Four places, one vocabulary.

   BRAUN, WHICH ON THIS ESTATE MEANS FLAT. A 4px corner on each of these — not
   the 8px of the house .btn and never the 999px of the pill — because they
   are the WHOIS page's controls arriving on this one, and that page is square
   throughout. A hovered key differs from a resting one by a SOLID INK FILL,
   not by a shape. Labels in tracked capitals, 10-11px, 700.

   The accent appears once per piece, as the small VIP tag, and as a FILL:
   --accent-fill with --on-accent type, the pair this sheet keeps for exactly
   that job (7.7:1 on paper; dark.css moves both, 6.8:1 on the moon side).
   Everything else is ink and hairline, so the key reads as the house's own and
   not as an advertisement stuck on it.

   Tokens throughout. The ribbon's two washes are the only literals, and they
   are answered in dark.css.
   ========================================================================== */

/* ---------------------------------------------------------------- the key --
   NOT a .btn, on purpose. The phone rule above hides `.nav__in > .btn` under
   640px to make room for the mark, the pill and the burger, and a VIP sharing
   that class would be the first thing to go on the screen most visitors hold.
   Its own class, its own phone sizing — measured, not estimated; see the two
   width rules at the end of this block.

   An ink outline beside the ink-filled Generate: the same palette, visibly a
   different kind of key. 40px tall, the burger's height, so the right-hand
   end of the bar is one row of equal keys. */
.vip {
    position: relative;   /* the phone tab, below, hangs off this corner */
    flex: 0 0 auto;
    display: inline-flex; align-items: center; gap: .5rem;
    height: 40px; padding: 0 .6rem 0 .8rem;
    border: 1px solid var(--ink); border-radius: 4px;
    background: transparent; color: var(--ink);
    font-size: .6875rem; font-weight: 700; letter-spacing: .12em;
    text-transform: uppercase; line-height: 1;
    text-decoration: none; white-space: nowrap;
    transition: background .22s var(--ease), color .22s var(--ease);
}
.vip:hover { background: var(--ink); color: var(--paper); }
/* The sheet-wide :focus-visible rule rounds whatever it rings to 3px. Equal
   specificity and later in the sheet, so this keeps the key's own corner. */
.vip:focus-visible { border-radius: 4px; }

/* The tag. 2px rather than 4: a label inside a key is one step squarer than
   the key, or the two corners argue. 9px capitals on the fill measure 7.7:1,
   so it can be this small and still be read rather than recognised. The same
   class is used in the menu row, where .menu__l's own span rule has to be
   answered — see below. */
.vip__tag {
    display: inline-flex; align-items: center;
    padding: .22rem .3rem .2rem; border-radius: 2px;
    background: var(--accent-fill); color: var(--on-accent);
    font-size: .5625rem; font-weight: 700; letter-spacing: .1em;
    line-height: 1; text-transform: uppercase;
}
/* `.menu__l span` makes every span in a menu label a block of secondary text.
   This one is a tag inside the bold line, so it takes back the four things
   that rule sets. (0,2,0) beats (0,1,1) — no !important needed. */
.menu__l .vip__tag {
    display: inline-flex; margin-left: .4rem; vertical-align: .14em;
    font-size: .5625rem; font-weight: 700; line-height: 1; color: var(--on-accent);
}

/* ------------------------------------------------------------- the ribbon --
   The slim strip at the top of the hero. It sits on the paper band, so its
   ground is a 2.2% ink wash — the same weight as the lookup record (.rec) —
   which is enough to read as a panel and not enough to compete with the h1
   under it. The tag stretches to the strip's full height, so on a phone, where
   the sentence wraps to two lines, the tag is a block beside both of them
   rather than a chip floating at the first. */
.hero__vip { margin: 0 0 1.9rem; }
.vip-ribbon {
    display: inline-flex; align-items: center; gap: .8rem;
    max-width: 100%; padding: .4rem .85rem .4rem .4rem;
    border: 1px solid var(--line); border-radius: 4px;
    background: rgba(30, 38, 43, .022);
    color: var(--ink-77); text-decoration: none;
    font-size: .86rem; line-height: 1.35;
    transition: border-color .22s var(--ease), background .22s var(--ease);
}
.vip-ribbon:hover { border-color: var(--ink); background: rgba(30, 38, 43, .045); }
.vip-ribbon:focus-visible { border-radius: 4px; }
.vip-ribbon__tag {
    flex: 0 0 auto; align-self: stretch;
    display: inline-flex; align-items: center;
    min-height: 26px; padding: 0 .5rem; border-radius: 2px;
    background: var(--accent-fill); color: var(--on-accent);
    font-size: .625rem; font-weight: 700; letter-spacing: .14em; line-height: 1;
}
.vip-ribbon__t { min-width: 0; }
.vip-ribbon__t b { color: var(--ink); font-weight: 600; letter-spacing: -.01em; }
/* What the engine speaks, as a panel label: the three protocols it asks in.
   Dropped on narrow screens, where the sentence needs the room. */
.vip-ribbon__meta {
    flex: 0 0 auto; padding-left: .8rem; border-left: 1px solid var(--line);
    font-size: .625rem; font-weight: 700; letter-spacing: .16em;
    text-transform: uppercase; color: var(--ink-55); white-space: nowrap;
}
.vip-ribbon__go {
    flex: 0 0 auto; font-style: normal; color: var(--ink);
    transition: transform .22s var(--ease);
}
.vip-ribbon:hover .vip-ribbon__go { transform: translateX(3px); }
@media (max-width: 760px) { .vip-ribbon__meta { display: none; } }
@media (max-width: 480px) { .vip-ribbon { gap: .6rem; font-size: .8rem; } }

/* ---------------------------------------------------------- the row link --
   "Full WHOIS report ↗" under each looked-up name (app.js, recordBlock). The
   record above it is the five fields RDAP gives a browser; this is the way on
   to everything else about the same name. A 34px key, the WHOIS page's control
   height, 40px under a finger. */
.rec__more { margin: .75rem 0 0; }
.rec__whois {
    display: inline-flex; align-items: center; gap: .5rem;
    min-height: 34px; padding: 0 .75rem;
    border: 1px solid var(--line); border-radius: 4px;
    color: var(--ink); text-decoration: none;
    font-size: .625rem; font-weight: 700; letter-spacing: .12em;
    text-transform: uppercase; line-height: 1;
    transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.rec__whois:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.rec__whois:focus-visible { border-radius: 4px; }
.rec__whois i { font-style: normal; font-size: 1.1em; color: var(--ink-55); }
.rec__whois:hover i { color: inherit; }
@media (pointer: coarse) { .rec__whois { min-height: 40px; } }

/* ------------------------------------------------------ the header budget --
   MEASURED, NOT ESTIMATED. tests/integration/harness.html walks the bar at 25
   widths from 320 to 1440 and adds up what each item asks for at its natural
   width. The first cut of this key was estimated, and the measurement found it
   wrong twice: at 320 the row asked for 21px more than it had and flexbox took
   them out of the burger, squeezing a 44px tap target to 22; and above 1100 the
   key and the new WHOIS link together asked for 1178px of a bar that is never
   wider than 1153 — it stops growing at the measure — so the section links were
   being crushed at every desktop width, 1440 included.

   So the homepage's bar — .nav__in--vip, the one carrying the key, the pill
   AND the burger — balances its budget by width band, and each band gives up
   the least valuable thing first. The numbers are what the row asks for
   against what it has, in the strict case: a 15px classic scrollbar in the
   viewport (a phone's overlay scrollbar gives every band 15px more).

     > 1340      everything; the bar's gaps close from 24px to 17.6, the
                 section links' from 30.4 to 24          1120 of 1153
     1181–1340   the "Domain Tools" subtitle goes — the house already drops it
                 under 980, for the same reason           984 of 1054–1153
     1101–1180   the section links go, as they already do under 1100; every
                 one of them is in the menu               709 of 976–1053
     641–760     the key gives up side padding            554 of 562–669
     481–640     (the house phone bar, and the key)       398 of 418–561
     381–480     the wordmark's text goes (the house drops it under 380); the
                 drawn mark stays, and still links home   298 of 326–417
     ≤ 380       the VIP tag lifts onto the key's corner as a tab, so the key
                 is only as wide as its word              257 of 265–325

   The tightest two bands, 641 and 320, keep 7.6px in hand. Anything added to
   this bar has to be measured against this table, not against a screenshot.
   ------------------------------------------------------------------------ */
@media (min-width: 1101px) {
    .nav__in--vip { gap: 1.1rem; }
    .nav__in--vip .nav__links { gap: 1.5rem; }
}
@media (min-width: 1101px) and (max-width: 1180px) {
    .nav__in--vip .nav__links { display: none; }
}
@media (min-width: 1181px) and (max-width: 1340px) {
    .nav__in--vip .nav__mark span { display: none; }
}
@media (max-width: 760px) {
    .vip { padding: 0 .5rem 0 .65rem; gap: .4rem; }
}
@media (max-width: 480px) {
    .nav__in--vip .nav__mark b { display: none; }
}
@media (max-width: 380px) {
    .nav__in--vip { gap: .45rem; }
    .nav__in--vip .vip { padding: 0 .5rem; }
    /* The tab: the same tag, taken out of the key's flow and hung on its top
       right corner, clear of the burger. The bar is 62px and the key 40, so it
       sits 4px below the bar's top edge and is never clipped. */
    .nav__in--vip .vip__tag {
        position: absolute; top: -7px; right: -4px; z-index: 1;
        padding: .16rem .24rem .14rem; font-size: .5rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .vip, .vip-ribbon, .vip-ribbon__go, .rec__whois { transition: none; }
    .vip-ribbon:hover .vip-ribbon__go { transform: none; }
}
/* A link is not a thing paper can do. The nav is already gone in print; the
   ribbon and the row link go with it. */
@media print {
    .hero__vip, .rec__more { display: none !important; }
}
/* -------------------------------------------------- hidden means hidden --
   Found in the WHOIS integration review, and older than it: the homepage's
   "Cancel lookups" key (#stop) and the shortlist bar (#list-box) are toggled
   with the `hidden` attribute by app.js (setRunUI, renderShortlistCount), but
   .btn and .out__bar set their own display, which outranks the browser's
   [hidden] rule — so both stood on the page from the first paint, a live
   Cancel with nothing to cancel and an empty shortlist bar. The same answer
   this sheet already gives .menu, .menu__row and .dial. */
.btn[hidden], .out__bar[hidden] { display: none; }

/* =============================================================================
   THE BAR ON ė.tv — the header budget, with the estate's keys in it
   -----------------------------------------------------------------------------
   ė.tv only; domainchaos.com has none of this. The budget above was
   measured on a bar of mark, links, pill, VIP key, Generate and burger. On
   ė.tv every bar also carries what the estate mounts at runtime: the
   assistant (.nav__bot, assistant.js) and the site search (.nav__find,
   search.js) — 44px squares on a phone, 53 and 55px with their Cmd-J / Cmd-K
   hints on a desktop — and the build chip (.labs-ver, version.js) inside the
   mark. Measured with those in place, natural widths against the room the bar
   has: the live homepage BEFORE the VIP key was already up to 93px over at
   381-481px and 130px over at 1101-1181px, and with the key it was up to 149px
   over — flexbox took it out of the burger, squeezing a 44px tap target to 20.

   So each domains bar gives up the least valuable thing first, and everything
   it gives up is still one tap away:
     the build chip     — also in the menu's head and in the footer
     the Cmd-J/K hints  — the shortcuts still work; only the hint goes
     the header pill    — the menu's foot carries the second one (never on the
                          404, which has no menu: its one pill always stays)
     the wordmark text  — the plate stays, and still links the labs home
   and never the VIP key, the search, the assistant or the burger.
   ========================================================================== */

/* ---- every domains bar ---- */
@media (max-width: 640px) {
    .nav__in .nav__mark .labs-ver { display: none; }
}
/* The house drops the wordmark under 380; with two more keys in the bar it
   goes under 400, and its link goes with it rather than standing empty with a
   gap on either side. The plate still links home. */
@media (max-width: 400px) {
    .nav__in .nav__mark b, .nav__in .nav__mark-self { display: none; }
}

/* ---- the VIP bars: the homepage's and the sitemap's ---- */
.nav__in--vip .nav__bot kbd, .nav__in--vip .nav__find kbd { display: none; }
@media (max-width: 1340px) {
    .nav__in--vip .nav__mark .labs-ver { display: none; }
}
@media (min-width: 1341px) {
    .nav__in--vip .nav__mark span { display: none; }
}
@media (min-width: 1181px) and (max-width: 1220px) {
    .nav__in--vip .nav__links { display: none; }
}
@media (min-width: 641px) and (max-width: 760px) {
    .nav__in--vip > .btn { display: none; }
}
@media (min-width: 481px) and (max-width: 640px) {
    .nav__in--vip { gap: .5rem; }
}
@media (max-width: 580px) {
    .nav__in--vip > .mode-pill { display: none; }
}
@media (max-width: 480px) {
    .nav__in--vip .nav__mark-self { display: none; }
}
@media (max-width: 380px) {
    .nav__in--vip { gap: .25rem; }
    .nav__in--vip .nav__bot, .nav__in--vip .nav__find { width: 40px; }
}

/* ---- the WHOIS page's bar ---- */
.wx-page .nav__in .nav__bot kbd, .wx-page .nav__in .nav__find kbd { display: none; }
@media (min-width: 1101px) and (max-width: 1180px) {
    .wx-page .nav__in .nav__links { display: none; }
}
@media (min-width: 1101px) and (max-width: 1340px) {
    .wx-page .nav__in .nav__mark span { display: none; }
}
@media (max-width: 460px) {
    .wx-page .nav__in > .mode-pill { display: none; }
}
