/* ==========================================================================
   iPrint3d — visual system

   Direction: a precision manufacturing supplier, not a hobbyist project page.
   The reference points are engineering drawings and spec sheets — light
   working surfaces, hairline rules, real data set in a monospace, and colour
   used only where it carries meaning.

   Two structural devices, both taken from the process itself:

     - the LAYER RULE: stacked hairlines standing in for deposited layers,
       used as the section divider throughout.
     - the BUILD PLATE: a faint square grid, the drawing-sheet cue, used
       behind the hero and the call-to-action panels.

   Colour is rationed. Orange is the hot nozzle and appears only on the
   primary action and on work in progress. Blue is structural and
   interactive. Everything else is ink on paper.

   The page is light; the header, footer and console sidebar are near-black
   bands. That is deliberate: the supplied logo is a chrome badge with a
   white outline, drawn to sit on a dark surface, and it needs one. If a flat
   or vector wordmark ever replaces it, those bands can go light too — the
   surface tokens below are the only thing that would need to change.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Typefaces — self-hosted.
   Served from this box rather than a font CDN, so the site keeps its
   typography on a LAN with no internet, loads faster, and makes no
   third-party requests. font-display:swap keeps text visible while the
   files fetch.
   -------------------------------------------------------------------------- */
@font-face {
    font-family: "Archivo";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("../fonts/archivo-latin-600-normal.woff2") format("woff2");
}
@font-face {
    font-family: "Archivo";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/archivo-latin-700-normal.woff2") format("woff2");
}
@font-face {
    font-family: "Archivo";
    font-style: normal;
    font-weight: 800;
    font-display: swap;
    src: url("../fonts/archivo-latin-800-normal.woff2") format("woff2");
}

@font-face {
    font-family: "IBM Plex Sans";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/ibm-plex-sans-latin-400-normal.woff2") format("woff2");
}
@font-face {
    font-family: "IBM Plex Sans";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("../fonts/ibm-plex-sans-latin-500-normal.woff2") format("woff2");
}
@font-face {
    font-family: "IBM Plex Sans";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("../fonts/ibm-plex-sans-latin-600-normal.woff2") format("woff2");
}

@font-face {
    font-family: "IBM Plex Mono";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2");
}
@font-face {
    font-family: "IBM Plex Mono";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("../fonts/ibm-plex-mono-latin-500-normal.woff2") format("woff2");
}

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */
:root {
    /* Working surfaces, lightest first */
    --paper:        #ffffff;
    --paper-sunk:   #f4f6f8;
    --paper-dim:    #eef1f5;
    --rule:         #e2e7ed;   /* hairlines between things */
    --edge:         #cbd3dc;   /* borders of things you can interact with */

    /* Dark bands: header, footer, console sidebar */
    --band:         #0f1319;
    --band-raised:  #171d26;
    --band-rule:    #262f3b;
    --band-ink:     #eef1f5;
    --band-ink-mid: #98a3b2;

    /* Ink */
    --ink:          #0f1319;   /* headings */
    --ink-body:     #39424f;   /* running text */
    --ink-mute:     #626d7c;   /* secondary */
    --ink-faint:    #838e9c;   /* labels, timestamps */

    /* Meaning. Every one of these is AA on white at body size. */
    --nozzle:       #c2410c;   /* the hot end: primary action, work in progress */
    --nozzle-deep:  #9a330a;
    --nozzle-tint:  #fdf1ea;
    --nozzle-line:  #f2c9b0;

    --filament:     #0b57d0;   /* structural, interactive */
    --filament-tint:#eef3fd;
    --filament-line:#c3d6f6;

    --ok:           #0d7a45;
    --ok-tint:      #eaf6f0;
    --ok-line:      #b4ded0;

    --alert:        #b42318;
    --alert-tint:   #fdefee;
    --alert-line:   #f3c4c0;

    /* Type */
    --display: "Archivo", "Helvetica Neue", Arial, sans-serif;
    --body: "IBM Plex Sans", -apple-system, "Segoe UI", Roboto, sans-serif;
    --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Consolas, monospace;

    /* Scale — tighter than a marketing site. This is a shop, not a billboard. */
    --step-0: 1rem;
    --step-1: 1.0625rem;
    --step-2: 1.25rem;
    --step-3: 1.5rem;
    --step-4: 2rem;
    --step-5: clamp(2.125rem, 4.2vw, 3rem);

    /* Geometry — square-ish. Precision does not have soft corners. */
    --r-sm: 2px;
    --r-md: 4px;
    --r-lg: 8px;

    --gutter: clamp(1.25rem, 4vw, 2.5rem);
    --measure: 68ch;
    --shell: 1200px;

    --shadow-sm: 0 1px 2px rgba(15, 19, 25, 0.06);
    --shadow-md: 0 2px 8px rgba(15, 19, 25, 0.07), 0 1px 2px rgba(15, 19, 25, 0.05);
    --shadow-lg: 0 12px 32px rgba(15, 19, 25, 0.10), 0 2px 6px rgba(15, 19, 25, 0.05);
}

/* --------------------------------------------------------------------------
   Reset & base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--paper-sunk);
    color: var(--ink-body);
    font-family: var(--body);
    font-size: var(--step-0);
    line-height: 1.62;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

img, video, svg { max-width: 100%; display: block; }

h1, h2, h3, h4 {
    font-family: var(--display);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.021em;
    color: var(--ink);
    margin: 0;
}

p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }

a { color: var(--filament); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

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

::selection { background: var(--nozzle); color: #fff; }

/* --------------------------------------------------------------------------
   Signature 1: the layer rule
   A stack of hairlines standing in for deposited print layers. Used wherever
   the page needs a divider, in place of a plain 1px border.
   -------------------------------------------------------------------------- */
.layer-rule {
    height: 4px;
    border: 0;
    margin: 0;
    background-image: repeating-linear-gradient(
        180deg,
        var(--edge) 0 1px,
        transparent 1px 3px
    );
}

/* Signature 2: the build plate — the drawing-sheet grid. */
.grid-plate {
    background-color: var(--paper);
    background-image:
        linear-gradient(to right,  rgba(15, 19, 25, 0.05) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(15, 19, 25, 0.05) 1px, transparent 1px);
    background-size: 26px 26px;
    background-position: -1px -1px;
}

/* --------------------------------------------------------------------------
   Utility type
   -------------------------------------------------------------------------- */
.eyebrow {
    font-family: var(--mono);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--nozzle);
    margin: 0 0 0.8rem;
    display: flex;
    align-items: center;
    gap: 0.6rem;
}
.eyebrow::before {
    content: "";
    width: 16px;
    height: 2px;
    background: var(--nozzle);
    flex: none;
}

.lede {
    font-size: var(--step-2);
    line-height: 1.55;
    color: var(--ink-mute);
    max-width: var(--measure);
}

/* Small technical caption: dates, file sizes, counts. */
.spec {
    font-family: var(--mono);
    font-size: 0.74rem;
    letter-spacing: 0.04em;
    color: var(--ink-faint);
    font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Shell
   -------------------------------------------------------------------------- */
.shell {
    max-width: var(--shell);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

.site-main { padding-block: clamp(2rem, 5vw, 3.5rem) clamp(3.5rem, 8vw, 5.5rem); }

.section { margin-block: clamp(2.75rem, 6vw, 4.5rem); }
.section:first-child { margin-top: 0; }

.page-head { margin-bottom: clamp(1.75rem, 4vw, 2.75rem); }
.page-head h1 { font-size: var(--step-4); margin-bottom: 0.5rem; }
.page-head .lede { margin-top: 0; }

/* --------------------------------------------------------------------------
   Header — a dark band, because the logo needs one
   -------------------------------------------------------------------------- */
.site-header {
    position: sticky;
    top: 0;
    z-index: 60;
    background: var(--band);
    border-bottom: 1px solid var(--band-rule);
}

.header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    min-height: 70px;
}

.brand {
    display: inline-flex;
    align-items: center;
    flex: none;
}
.brand:hover { text-decoration: none; }
.brand img { height: 40px; width: auto; }
@media (max-width: 520px) {
    .brand img { height: 32px; }
}

.main-nav ul {
    display: flex;
    align-items: center;
    gap: 0.1rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.main-nav a {
    display: inline-block;
    padding: 0.5rem 0.75rem;
    border-radius: var(--r-sm);
    color: var(--band-ink-mid);
    font-size: 0.895rem;
    font-weight: 500;
    transition: color 0.15s ease, background-color 0.15s ease;
}
.main-nav a:hover {
    color: var(--band-ink);
    background: rgba(255, 255, 255, 0.06);
    text-decoration: none;
}
.main-nav a[aria-current="page"] {
    color: var(--band-ink);
    box-shadow: inset 0 -2px 0 var(--nozzle);
}

/* The live link carries a status dot — it is the one nav item whose state
   changes, so it earns the extra weight.
   Note the selector is scoped under .main-nav: a bare .nav-live (0,1,0)
   loses to .main-nav a (0,1,1) above, which would leave the link inline
   and cause the dot to paint as a full-height bar. */
.main-nav .nav-live {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}
.main-nav .nav-live::before {
    content: "";
    display: block;
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #35d07f;
    box-shadow: 0 0 0 0 rgba(53, 208, 127, 0.55);
    animation: pulse 2.4s ease-out infinite;
}

@keyframes pulse {
    0%   { box-shadow: 0 0 0 0 rgba(53, 208, 127, 0.5); }
    70%  { box-shadow: 0 0 0 7px rgba(53, 208, 127, 0); }
    100% { box-shadow: 0 0 0 0 rgba(53, 208, 127, 0); }
}

/* The one nav item that is an action rather than a destination. */
.main-nav .nav-cta {
    margin-left: 0.5rem;
    padding: 0.55rem 1.05rem;
    border-radius: var(--r-sm);
    background: var(--nozzle);
    color: #fff;
    font-weight: 600;
}
.main-nav .nav-cta:hover {
    background: #d94d13;
    color: #fff;
}
.main-nav .nav-cta[aria-current="page"] { box-shadow: none; }

.nav-toggle {
    display: none;
    background: transparent;
    border: 1px solid var(--band-rule);
    color: var(--band-ink);
    border-radius: var(--r-sm);
    padding: 0.45rem 0.7rem;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}

@media (max-width: 900px) {
    .nav-toggle { display: block; }
    .main-nav ul {
        display: none;
        position: absolute;
        right: var(--gutter);
        top: calc(100% + 8px);
        flex-direction: column;
        align-items: stretch;
        min-width: 220px;
        padding: 0.5rem;
        gap: 2px;
        background: var(--band-raised);
        border: 1px solid var(--band-rule);
        border-radius: var(--r-md);
        box-shadow: var(--shadow-lg);
    }
    .main-nav ul.open { display: flex; }
    .main-nav a { padding: 0.65rem 0.8rem; }
    .main-nav .nav-cta { margin: 0.35rem 0 0; text-align: center; }
}

/* --------------------------------------------------------------------------
   Hero — copy and evidence side by side, the way a supplier presents itself
   -------------------------------------------------------------------------- */
.hero {
    display: grid;
    grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
    align-items: stretch;
    gap: 0;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    overflow: hidden;
    box-shadow: var(--shadow-md);
}

.hero-figure {
    order: 2;
    position: relative;
    min-height: 100%;
    background: var(--band);
}
.hero-figure img {
    width: 100%;
    height: 100%;
    min-height: 340px;
    object-fit: cover;
    object-position: center;
}

.hero-body {
    order: 1;
    padding: clamp(1.75rem, 3.5vw, 3rem);
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.hero-body h1 {
    font-size: var(--step-5);
    letter-spacing: -0.028em;
    max-width: 16ch;
    margin-bottom: 0.85rem;
}
.hero-body h1 em {
    font-style: normal;
    color: var(--nozzle);
}

.hero-body .lede { margin-bottom: 1.6rem; }

.hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem;
    align-items: center;
}

/* The spec strip: the three facts a prospective customer checks first. */
.hero-specs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 0;
    margin: 1.75rem 0 0;
    padding-top: 1.25rem;
    border-top: 1px solid var(--rule);
}
.hero-specs div { padding-right: 1.25rem; }
.hero-specs dt {
    font-family: var(--mono);
    font-size: 0.68rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-faint);
    margin: 0 0 0.3rem;
}
.hero-specs dd {
    margin: 0;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--ink);
}

@media (max-width: 860px) {
    .hero { grid-template-columns: 1fr; }
    .hero-figure { order: 2; }
    .hero-figure img { min-height: 0; aspect-ratio: 16 / 9; }
    .hero-body { order: 1; }
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.7rem 1.3rem;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    font-family: var(--body);
    font-size: 0.925rem;
    font-weight: 600;
    line-height: 1.3;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease,
                color 0.15s ease, box-shadow 0.15s ease;
}
.btn:hover { text-decoration: none; }

.btn-primary {
    background: var(--nozzle);
    border-color: var(--nozzle);
    color: #fff;
}
.btn-primary:hover {
    background: var(--nozzle-deep);
    border-color: var(--nozzle-deep);
    color: #fff;
    box-shadow: var(--shadow-sm);
}

.btn-ghost {
    background: var(--paper);
    border-color: var(--edge);
    color: var(--ink);
}
.btn-ghost:hover {
    border-color: var(--ink-mute);
    background: var(--paper);
    color: var(--ink);
}

.btn-quiet {
    background: transparent;
    border-color: var(--rule);
    color: var(--ink-mute);
}
.btn-quiet:hover {
    border-color: var(--edge);
    background: var(--paper);
    color: var(--ink);
}

.btn-danger {
    background: var(--paper);
    border-color: var(--alert-line);
    color: var(--alert);
}
.btn-danger:hover {
    background: var(--alert-tint);
    border-color: var(--alert);
    color: var(--alert);
}

.btn-sm { padding: 0.44rem 0.85rem; font-size: 0.84rem; }
.btn-block { display: flex; width: 100%; }

.btn:disabled,
.btn[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }

.btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem;
    align-items: center;
}

.link-arrow {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-family: var(--mono);
    font-size: 0.76rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.link-arrow::after {
    content: "\2192";
    transition: transform 0.18s ease;
}
.link-arrow:hover { text-decoration: none; }
.link-arrow:hover::after { transform: translateX(4px); }

/* --------------------------------------------------------------------------
   Breadcrumbs
   -------------------------------------------------------------------------- */
.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    list-style: none;
    margin: 0 0 1rem;
    padding: 0;
    font-size: 0.8rem;
    color: var(--ink-faint);
}
.breadcrumb li + li::before {
    content: "/";
    margin-right: 0.45rem;
    color: var(--edge);
}
.breadcrumb a { color: var(--ink-mute); }

/* --------------------------------------------------------------------------
   Services — a capability table, one hairline apart
   -------------------------------------------------------------------------- */
.service-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1px;
    background: var(--rule);
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    overflow: hidden;
}

.service {
    background: var(--paper);
    padding: 1.5rem 1.5rem 1.6rem;
    transition: background-color 0.18s ease;
}
.service:hover { background: var(--paper-dim); }

.service h3 {
    font-size: var(--step-1);
    margin-bottom: 0.4rem;
}
.service p {
    color: var(--ink-mute);
    font-size: 0.9rem;
    line-height: 1.6;
}

/* --------------------------------------------------------------------------
   Cards & media grid
   -------------------------------------------------------------------------- */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1.25rem;
}

.card {
    display: flex;
    flex-direction: column;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    overflow: hidden;
    transition: border-color 0.18s ease, box-shadow 0.18s ease,
                transform 0.18s ease;
}
.card:hover {
    border-color: var(--edge);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}

.card-media {
    position: relative;
    background: var(--band);
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-bottom: 1px solid var(--rule);
}
.card-media img,
.card-media video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.card-media img { transition: transform 0.45s cubic-bezier(0.2, 0.7, 0.3, 1); }
.card:hover .card-media img { transform: scale(1.03); }

.card-body {
    padding: 1.1rem 1.2rem 1.15rem;
    display: flex;
    flex-direction: column;
    flex: 1;
}
.card-body h3 { font-size: var(--step-1); margin-bottom: 0.35rem; }
.card-body p {
    color: var(--ink-mute);
    font-size: 0.9rem;
    flex: 1;
}
.card-foot {
    margin-top: 0.85rem;
    padding-top: 0.7rem;
    border-top: 1px solid var(--rule);
}

/* Routing cards used on the home page to send people into the sections. */
.route-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
    gap: 1.1rem;
}

.route {
    display: flex;
    flex-direction: column;
    padding: 1.5rem 1.5rem 1.4rem;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    color: inherit;
    transition: border-color 0.18s ease, box-shadow 0.18s ease,
                transform 0.18s ease;
}
.route:hover {
    text-decoration: none;
    border-color: var(--edge);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}
.route h3 { font-size: var(--step-2); margin-bottom: 0.45rem; }
.route p {
    color: var(--ink-mute);
    font-size: 0.9rem;
    flex: 1;
}
.route-go {
    margin-top: 1.1rem;
    font-family: var(--mono);
    font-size: 0.74rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--filament);
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}
.route:hover .route-go { color: var(--nozzle); }
.route-go span { transition: transform 0.18s ease; }
.route:hover .route-go span { transform: translateX(4px); }

/* --------------------------------------------------------------------------
   Live camera — the one place that stays dark, because the subject is
   -------------------------------------------------------------------------- */
.stage {
    position: relative;
    border: 1px solid var(--band-rule);
    border-radius: var(--r-md);
    overflow: hidden;
    background: #05070a;
    aspect-ratio: 16 / 9;
    box-shadow: var(--shadow-lg);
}
.stage img,
.stage iframe {
    width: 100%;
    height: 100%;
    object-fit: contain;
    border: 0;
    display: block;
}

.stage-badge {
    position: absolute;
    top: 0.85rem;
    left: 0.85rem;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    background: rgba(5, 7, 10, 0.78);
    backdrop-filter: blur(6px);
    border: 1px solid rgba(255, 255, 255, 0.14);
    font-family: var(--mono);
    font-size: 0.68rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #fff;
    pointer-events: none;
}
.stage-badge::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #35d07f;
    animation: pulse 2.4s ease-out infinite;
}

/* Camera switched off from the console. It keeps the stage's exact footprint
   so the page does not jump around when the feed comes back on. */
.stage-offline {
    display: grid;
    place-content: center;
    justify-items: center;
    height: 100%;
    padding: clamp(1.5rem, 5vw, 3rem);
    text-align: center;
    background-image:
        linear-gradient(to right,  rgba(255, 255, 255, 0.03) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
    background-size: 26px 26px;
}
.stage-offline-label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1rem;
    padding: 0.3rem 0.7rem;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 999px;
    font-family: var(--mono);
    font-size: 0.68rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #98a3b2;
}
.stage-offline-label::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #58626f;
}
.stage-offline h2 {
    color: #fff;
    font-size: var(--step-3);
    margin-bottom: 0.6rem;
}
.stage-offline p {
    color: #98a3b2;
    font-size: 0.95rem;
    line-height: 1.6;
    max-width: 46ch;
    margin: 0;
}

.stage-note {
    margin-top: 1rem;
    color: var(--ink-mute);
    font-size: 0.88rem;
    max-width: var(--measure);
}

/* --------------------------------------------------------------------------
   Contact cards
   -------------------------------------------------------------------------- */
.contact-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 1rem;
}

.contact-card {
    padding: 1.25rem 1.35rem;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    margin: 0;
}
.contact-card dt {
    font-family: var(--mono);
    font-size: 0.68rem;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--ink-faint);
    margin-bottom: 0.45rem;
}
.contact-card dd {
    margin: 0;
    font-size: var(--step-1);
    font-weight: 600;
    color: var(--ink);
}

/* --------------------------------------------------------------------------
   Prose
   -------------------------------------------------------------------------- */
.prose {
    max-width: var(--measure);
    color: var(--ink-body);
    font-size: var(--step-1);
    line-height: 1.72;
}
.prose p { margin-bottom: 1.1rem; }
.prose strong { color: var(--ink); font-weight: 600; }

/* --------------------------------------------------------------------------
   Empty states — an invitation, not a shrug
   -------------------------------------------------------------------------- */
.empty {
    padding: clamp(2.25rem, 6vw, 4rem) 1.5rem;
    text-align: center;
    background: var(--paper);
    border: 1px dashed var(--edge);
    border-radius: var(--r-md);
}
.empty h3 { font-size: var(--step-2); margin-bottom: 0.45rem; }
.empty p { color: var(--ink-mute); margin-inline: auto; max-width: 44ch; }

/* --------------------------------------------------------------------------
   Panels and forms
   -------------------------------------------------------------------------- */
.panel {
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    padding: clamp(1.25rem, 3vw, 1.75rem);
}
.panel-narrow { max-width: 460px; }

/* The panel that holds the primary action. */
.panel-accent {
    border-color: var(--nozzle-line);
    background:
        linear-gradient(180deg, var(--nozzle-tint), var(--paper) 120px);
}

.field { margin-bottom: 1.1rem; }
.field:last-child { margin-bottom: 0; }
.field label {
    display: block;
    margin-bottom: 0.35rem;
    font-size: 0.84rem;
    font-weight: 600;
    color: var(--ink);
}

.field input[type="text"],
.field input[type="password"],
.field input[type="email"],
.field input[type="tel"],
.field input[type="url"],
.field input[type="date"],
.field input[type="number"],
.field input[type="search"],
.field input[type="file"],
.field select,
.field textarea {
    width: 100%;
    padding: 0.62rem 0.75rem;
    background: var(--paper);
    border: 1px solid var(--edge);
    border-radius: var(--r-sm);
    color: var(--ink);
    font-family: var(--body);
    font-size: 0.94rem;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.field input::placeholder,
.field textarea::placeholder { color: var(--ink-faint); }

.field select {
    /* Native arrow, drawn rather than imported, so the control matches on
       every platform. */
    appearance: none;
    background-image:
        linear-gradient(45deg, transparent 50%, var(--ink-mute) 50%),
        linear-gradient(135deg, var(--ink-mute) 50%, transparent 50%);
    background-position:
        calc(100% - 17px) calc(50% + 1px),
        calc(100% - 12px) calc(50% + 1px);
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
    padding-right: 2.3rem;
    cursor: pointer;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
    outline: none;
    border-color: var(--filament);
    box-shadow: 0 0 0 3px var(--filament-tint);
}
.field input:disabled {
    background: var(--paper-dim);
    color: var(--ink-faint);
}
.field textarea { min-height: 96px; resize: vertical; line-height: 1.6; }

.field-hint {
    margin: 0.35rem 0 0;
    font-size: 0.815rem;
    line-height: 1.5;
    color: var(--ink-mute);
}
.field-error {
    margin: 0.35rem 0 0;
    font-size: 0.815rem;
    font-weight: 500;
    color: var(--alert);
}
.field.has-error input,
.field.has-error select,
.field.has-error textarea { border-color: var(--alert); }

.field-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0 1rem;
}
.field-row-thirds { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }

.req { color: var(--nozzle); }

.field-legend {
    display: block;
    margin-bottom: 0.5rem;
    font-size: 0.84rem;
    font-weight: 600;
    color: var(--ink);
}

/* Checkbox and radio rows, with the control aligned to the first line of a
   label that may run to three. */
.checkbox {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.65rem;
    align-items: start;
    margin-bottom: 0.8rem;
    font-size: 0.89rem;
    line-height: 1.55;
    color: var(--ink-body);
    cursor: pointer;
}
.checkbox input {
    margin: 0.2rem 0 0;
    width: 1rem;
    height: 1rem;
    accent-color: var(--nozzle);
    cursor: pointer;
}

/* Radio cards — used where the choice deserves a sentence of explanation. */
.choice-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
    gap: 0.55rem;
}
.choice { position: relative; display: block; cursor: pointer; }
.choice input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.choice-box {
    display: block;
    height: 100%;
    padding: 0.8rem 0.95rem;
    background: var(--paper);
    border: 1px solid var(--edge);
    border-radius: var(--r-sm);
    transition: border-color 0.15s ease, background-color 0.15s ease,
                box-shadow 0.15s ease;
}
.choice:hover .choice-box { border-color: var(--ink-mute); }
.choice input:checked + .choice-box {
    border-color: var(--nozzle);
    background: var(--nozzle-tint);
    box-shadow: inset 0 0 0 1px var(--nozzle);
}
.choice input:focus-visible + .choice-box {
    outline: 2px solid var(--nozzle);
    outline-offset: 2px;
}
.choice-name {
    display: block;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--ink);
    margin-bottom: 0.1rem;
}
.choice-note {
    display: block;
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--ink-mute);
}

/* Numbered form sections — they turn a long form into a short list of
   short forms, which is the only thing that makes a long form bearable. */
.form-section {
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    padding: clamp(1.25rem, 3vw, 1.75rem);
    margin-bottom: 1.1rem;
}
.form-section:last-of-type { margin-bottom: 0; }
.form-section-title {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    font-family: var(--display);
    font-size: var(--step-2);
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ink);
    margin-bottom: 0.4rem;
}
.form-section-num {
    flex: none;
    display: inline-grid;
    place-items: center;
    width: 1.8rem;
    height: 1.8rem;
    border-radius: var(--r-sm);
    background: var(--band);
    color: #fff;
    font-family: var(--mono);
    font-size: 0.76rem;
    font-weight: 500;
}
.form-section-note {
    color: var(--ink-mute);
    font-size: 0.9rem;
    max-width: 62ch;
    margin-bottom: 1.3rem;
}

.form-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(280px, 340px);
    gap: clamp(1.1rem, 2.5vw, 1.75rem);
    align-items: start;
}
@media (max-width: 940px) {
    .form-grid { grid-template-columns: 1fr; }
}

/* The sticky submit rail beside a long form. */
.form-rail { position: sticky; top: 90px; }
@media (max-width: 940px) {
    .form-rail { position: static; }
}

/* Attached-file list on the request form. */
.file-list {
    list-style: none;
    margin: 0.7rem 0 0;
    padding: 0;
    font-size: 0.86rem;
}
.file-list li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.45rem 0;
    border-bottom: 1px solid var(--rule);
    color: var(--ink-body);
}
.file-list li:last-child { border-bottom: 0; }
.file-list .file-size {
    font-family: var(--mono);
    font-size: 0.74rem;
    color: var(--ink-faint);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* The honeypot. Off-screen rather than display:none — some bots skip hidden
   fields, but almost none skip one that is merely positioned away. */
.hp-field {
    position: absolute;
    left: -9999px;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* --------------------------------------------------------------------------
   Notices and flash messages
   -------------------------------------------------------------------------- */
.notice,
.flash {
    padding: 0.85rem 1.05rem;
    border-radius: var(--r-sm);
    border: 1px solid;
    border-left-width: 3px;
    margin-bottom: 1.15rem;
    font-size: 0.91rem;
    line-height: 1.6;
}
.flash:last-child { margin-bottom: 0; }
.flash a { text-decoration: underline; text-underline-offset: 2px; }
.flash strong { font-weight: 600; }

.flash-success, .notice-ok {
    background: var(--ok-tint);
    border-color: var(--ok-line);
    border-left-color: var(--ok);
    color: #0a5c35;
}
.flash-error, .notice-error {
    background: var(--alert-tint);
    border-color: var(--alert-line);
    border-left-color: var(--alert);
    color: #8f1c14;
}
.flash-warning {
    background: var(--nozzle-tint);
    border-color: var(--nozzle-line);
    border-left-color: var(--nozzle);
    color: var(--nozzle-deep);
}
.flash-info {
    background: var(--filament-tint);
    border-color: var(--filament-line);
    border-left-color: var(--filament);
    color: #0a3f96;
}
.notice code,
.flash code {
    font-family: var(--mono);
    font-size: 0.86em;
    background: rgba(15, 19, 25, 0.06);
    padding: 0.1em 0.4em;
    border-radius: 2px;
}

/* --------------------------------------------------------------------------
   Status pills

   The pipeline reads left to right in colour as well as in words: blue while
   the shop is thinking, orange while it is working, green when it is done,
   red when it is not happening.
   -------------------------------------------------------------------------- */
.pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.22rem 0.6rem;
    border-radius: 999px;
    border: 1px solid;
    font-family: var(--mono);
    font-size: 0.685rem;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    line-height: 1.6;
}
.pill::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.pill-pending   { color: var(--nozzle);   border-color: var(--nozzle-line);   background: var(--nozzle-tint); }
.pill-quoted    { color: var(--filament); border-color: var(--filament-line); background: var(--filament-tint); }
.pill-scheduled { color: var(--filament); border-color: var(--filament-line); background: var(--filament-tint); }
.pill-printing  { color: var(--nozzle);   border-color: var(--nozzle);        background: var(--nozzle-tint); }
.pill-ready     { color: var(--ok);       border-color: var(--ok-line);       background: var(--ok-tint); }
.pill-completed { color: var(--ink-mute); border-color: var(--edge);          background: var(--paper-dim); }
.pill-declined  { color: var(--alert);    border-color: var(--alert-line);    background: var(--alert-tint); }
.pill-cancelled { color: var(--ink-faint);border-color: var(--rule);          background: transparent; }

/* The one status that is genuinely happening right now gets a heartbeat, the
   same one the live-camera dot uses. */
.pill-printing::before { animation: pulse 2.4s ease-out infinite; }

/* --------------------------------------------------------------------------
   Key/value detail lists — the request record, and the public status page
   -------------------------------------------------------------------------- */
.kv { border-top: 1px solid var(--rule); }
.kv-row {
    display: grid;
    grid-template-columns: minmax(130px, 200px) 1fr;
    gap: 1.25rem;
    padding: 0.8rem 0;
    border-bottom: 1px solid var(--rule);
    font-size: 0.92rem;
}
.kv-row:last-child { border-bottom: 0; }
.kv-key {
    font-family: var(--mono);
    font-size: 0.685rem;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    color: var(--ink-faint);
    padding-top: 0.2rem;
}
.kv-val { color: var(--ink-body); word-break: break-word; min-width: 0; }
.kv-val strong { color: var(--ink); font-weight: 600; }
.kv-val-pre { white-space: pre-wrap; }
@media (max-width: 560px) {
    .kv-row { grid-template-columns: 1fr; gap: 0.2rem; }
}

/* --------------------------------------------------------------------------
   Notes — internal notes, staff replies, quoted customer messages
   -------------------------------------------------------------------------- */
.note {
    padding: 0.95rem 1.1rem;
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    background: var(--paper-sunk);
    margin-bottom: 0.8rem;
}
.note:last-child { margin-bottom: 0; }
.note-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.7rem;
    margin-bottom: 0.5rem;
    font-family: var(--mono);
    font-size: 0.71rem;
    letter-spacing: 0.05em;
    color: var(--ink-faint);
}
.note-author { color: var(--nozzle); text-transform: uppercase; font-weight: 500; }
.note-body {
    margin: 0;
    color: var(--ink-body);
    font-size: 0.92rem;
    line-height: 1.65;
    white-space: pre-wrap;
}
.note-outbound {
    border-left: 3px solid var(--filament);
    background: var(--filament-tint);
}
.note-unread { border-color: var(--edge); background: var(--paper); }

.unread-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--nozzle);
    margin-right: 0.45rem;
    vertical-align: middle;
}

/* --------------------------------------------------------------------------
   The public status card
   -------------------------------------------------------------------------- */
.status-card {
    padding: clamp(1.5rem, 4vw, 2.5rem);
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-md);
}
.status-ref {
    font-family: var(--mono);
    font-size: clamp(1.4rem, 4.5vw, 1.9rem);
    font-weight: 500;
    letter-spacing: 0.07em;
    color: var(--ink);
}

/* The pipeline, drawn as the layer stack it is. */
.track {
    display: flex;
    flex-wrap: wrap;
    gap: 0;
    margin: 1.5rem 0;
    list-style: none;
    padding: 0;
}
.track li {
    flex: 1 1 105px;
    padding: 0.65rem 0.5rem 0;
    border-top: 3px solid var(--rule);
    font-size: 0.78rem;
    color: var(--ink-faint);
}
.track li.is-done { border-top-color: var(--filament); color: var(--ink-mute); }
.track li.is-current {
    border-top-color: var(--nozzle);
    color: var(--ink);
    font-weight: 600;
}
.track li.is-stopped {
    border-top-color: var(--alert);
    color: var(--alert);
    font-weight: 600;
}

/* --------------------------------------------------------------------------
   Process steps
   -------------------------------------------------------------------------- */
.steps {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 1.5rem;
    counter-reset: step;
    list-style: none;
    margin: 0;
    padding: 0;
}
.steps li { counter-increment: step; }
.steps li::before {
    content: counter(step, decimal-leading-zero);
    display: block;
    font-family: var(--mono);
    font-size: 0.76rem;
    font-weight: 500;
    letter-spacing: 0.14em;
    color: var(--nozzle);
    padding-bottom: 0.65rem;
    margin-bottom: 0.85rem;
    border-bottom: 1px solid var(--rule);
}
.steps h3 { font-size: var(--step-1); margin-bottom: 0.35rem; }
.steps p { color: var(--ink-mute); font-size: 0.9rem; }

/* --------------------------------------------------------------------------
   Spec sheet — materials and detail levels
   -------------------------------------------------------------------------- */
.spec-list {
    display: grid;
    gap: 1px;
    background: var(--rule);
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    overflow: hidden;
}
.spec-item {
    display: grid;
    grid-template-columns: minmax(120px, 180px) 1fr;
    gap: 1.25rem;
    padding: 1.1rem 1.35rem;
    background: var(--paper);
    margin: 0;
}
.spec-item dt {
    font-family: var(--display);
    font-size: var(--step-1);
    font-weight: 700;
    letter-spacing: -0.018em;
    color: var(--ink);
}
.spec-item dd {
    margin: 0;
    color: var(--ink-mute);
    font-size: 0.91rem;
    line-height: 1.6;
}
@media (max-width: 620px) {
    .spec-item { grid-template-columns: 1fr; gap: 0.3rem; }
}

/* --------------------------------------------------------------------------
   Call-to-action band — the one place the build plate shows through
   -------------------------------------------------------------------------- */
.cta-band {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: clamp(1.5rem, 4vw, 2.25rem);
    border: 1px solid var(--edge);
    border-radius: var(--r-lg);
    background-color: var(--paper);
    background-image:
        linear-gradient(to right,  rgba(15, 19, 25, 0.05) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(15, 19, 25, 0.05) 1px, transparent 1px);
    background-size: 26px 26px;
    background-position: -1px -1px;
}
.cta-band h2 { font-size: var(--step-3); margin-bottom: 0.35rem; }
.cta-band p { color: var(--ink-mute); max-width: 48ch; }

/* --------------------------------------------------------------------------
   FAQ disclosure
   -------------------------------------------------------------------------- */
.faq {
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    overflow: hidden;
    background: var(--paper);
}
.faq details { border-bottom: 1px solid var(--rule); }
.faq details:last-child { border-bottom: 0; }
.faq summary {
    padding: 1rem 1.3rem;
    cursor: pointer;
    font-weight: 600;
    font-size: 0.96rem;
    color: var(--ink);
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    transition: background-color 0.15s ease;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
    content: "+";
    flex: none;
    font-family: var(--mono);
    font-size: 1.05rem;
    color: var(--nozzle);
    transition: transform 0.2s ease;
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq summary:hover { background: var(--paper-dim); }
.faq-body {
    padding: 0 1.3rem 1.2rem;
    color: var(--ink-mute);
    font-size: 0.91rem;
    line-height: 1.7;
    max-width: 72ch;
}

/* --------------------------------------------------------------------------
   Stat tiles and data tables.
   Shared: the console (assets/css/admin.css) builds on these rather than
   restating them.
   -------------------------------------------------------------------------- */
.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1rem;
    margin-bottom: 2rem;
}
.stat {
    padding: 1.25rem 1.35rem;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
}
.stat dt {
    font-family: var(--mono);
    font-size: 0.7rem;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--ink-faint);
    margin-bottom: 0.5rem;
}
.stat dd {
    margin: 0;
    font-family: var(--display);
    font-size: var(--step-4);
    font-weight: 700;
    line-height: 1;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.table-wrap {
    border: 1px solid var(--rule);
    border-radius: var(--r-md);
    overflow: hidden;
}
table.data {
    width: 100%;
    border-collapse: collapse;
    background: var(--paper);
}
table.data th,
table.data td {
    padding: 0.75rem 0.95rem;
    text-align: left;
    vertical-align: middle;
    border-bottom: 1px solid var(--rule);
}
table.data th {
    font-family: var(--mono);
    font-size: 0.685rem;
    font-weight: 500;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    color: var(--ink-faint);
    background: var(--paper-sunk);
    white-space: nowrap;
}
table.data td { font-size: 0.905rem; color: var(--ink-body); }
table.data tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover { background: var(--paper-sunk); }

table.data .thumb {
    width: 78px;
    height: 56px;
    object-fit: cover;
    border-radius: var(--r-sm);
    border: 1px solid var(--rule);
}
table.data .cell-desc { color: var(--ink-mute); max-width: 34ch; }
table.data .cell-date,
table.data td.mono,
table.data .mono {
    font-family: var(--mono);
    font-size: 0.8rem;
    letter-spacing: 0.02em;
    font-variant-numeric: tabular-nums;
}
table.data td.num { font-variant-numeric: tabular-nums; text-align: right; }
table.data td.actions { text-align: right; white-space: nowrap; }

/* Two-line cell: the thing, then what qualifies it.
   Deliberately NOT scoped to table.data — the same pairing is used inside
   .kv-val on the request and dashboard screens, and an inline .row-sub there
   runs straight on from the line above it. */
.row-name {
    display: block;
    color: var(--ink);
    font-weight: 600;
}
.row-sub {
    display: block;
    font-size: 0.79rem;
    font-weight: 400;
    color: var(--ink-faint);
    margin-top: 0.1rem;
}
/* A job that needs attention gets a nozzle-coloured margin mark. */
table.data tr.is-overdue td:first-child { box-shadow: inset 3px 0 0 var(--nozzle); }

@media (max-width: 760px) {
    .table-wrap { overflow-x: auto; }
    table.data { min-width: 660px; }
}

.inline-form { display: inline; }

/* --------------------------------------------------------------------------
   Footer — the closing dark band
   -------------------------------------------------------------------------- */
.site-footer {
    background: var(--band);
    color: var(--band-ink-mid);
    padding-block: clamp(2.5rem, 5vw, 3.25rem) 1.5rem;
}

.footer-grid {
    display: grid;
    grid-template-columns: 1.5fr 1fr 1fr;
    gap: 2.5rem;
    padding-bottom: 2rem;
}
@media (max-width: 760px) {
    .footer-grid { grid-template-columns: 1fr; gap: 1.75rem; }
}

.footer-about p {
    color: var(--band-ink-mid);
    font-size: 0.89rem;
    max-width: 36ch;
}

.footer-col h4 {
    font-family: var(--mono);
    font-size: 0.7rem;
    font-weight: 500;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--band-ink);
    margin-bottom: 0.8rem;
}
.footer-col ul { list-style: none; margin: 0; padding: 0; }
.footer-col li { margin-bottom: 0.45rem; }
.footer-col a { color: var(--band-ink-mid); font-size: 0.9rem; }
.footer-col a:hover { color: var(--band-ink); }

.footer-base {
    padding-top: 1.25rem;
    border-top: 1px solid var(--band-rule);
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem 1.5rem;
    justify-content: space-between;
    align-items: center;
}
.footer-base p { color: #6d7887; font-size: 0.8rem; margin: 0; }
.footer-base a { color: #6d7887; font-size: 0.8rem; }
.footer-base a:hover { color: var(--band-ink); }

/* --------------------------------------------------------------------------
   Accessibility utilities
   -------------------------------------------------------------------------- */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* --------------------------------------------------------------------------
   Reveal-on-scroll. Opt-in via .reveal, and a no-op when the visitor has
   asked for reduced motion (see the block at the end of this file).
   -------------------------------------------------------------------------- */
.reveal {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.2, 0.7, 0.3, 1);
}
.reveal.is-visible { opacity: 1; transform: none; }
.no-js .reveal { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   Motion preferences
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }
    .reveal { opacity: 1; transform: none; }
}
