/* =====================================================================================
   The design system of this site (direction A: dark, glass, amber light)

   The owner chose direction A on 2026-09-28. One theme, one place for every colour:
   pages use the tokens below and never a raw hex value of their own.

   Sections: tokens Ã‚Â· reset Ã‚Â· layout Ã‚Â· header Ã‚Â· buttons Ã‚Â· hero Ã‚Â· cards Ã‚Â· calculator Ã‚Â·
             about Ã‚Â· contact Ã‚Â· back office preview Ã‚Â· footer Ã‚Â· forms Ã‚Â· responsive
   ===================================================================================== */

/* ---------------------------------- tokens ---------------------------------- */
:root {
    --font-sans: system-ui, "Segoe UI", Roboto, Arial, sans-serif;
    --font-heading: Georgia, "Times New Roman", serif;

    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;
    --space-7: 48px;
    --space-8: 72px;

    --radius-sm: 8px;
    --radius-md: 14px;
    --radius-lg: 22px;
    --radius-pill: 999px;

    --wrap: 1180px;

    /* dark, glass, amber */
    --page-bg: #0b0a09;
    --page-ink: #f6f2ea;
    --muted: #a99f92;
    --line: rgba(255, 255, 255, .14);
    --card-bg: rgba(255, 255, 255, .14);
    --card-line: rgba(255, 255, 255, .24);
    --card-shadow: 0 8px 32px rgba(0, 0, 0, .32);
    /* ONE grammar, three recipes for a surface (the owner's word, 2026-10-01; the values follow what the
       styles actually are, not a pale idea of them).
       A card, a panel and a section read the same tokens, and the AREA decides which recipe they carry:
       `glass` everywhere by default, `clay` inside the two surfaces a COMPANY looks at, `quiet` for the
       worker's tool on a phone.
       Depth belongs to the CONTAINER: buttons, fields and table rows never take it - a control stays crisp
       and a number stays readable.

       GLASS is four things together (drop any one and it stops being glass): a blur of the backdrop, a
       semi-transparent fill, a hairline light edge, and a soft shadow. The blur belongs in the teens - at
       6px it reads as a smudge on a dark page, which is exactly why the first attempt looked like "no
       change at all". `saturate(150%)` rides along because a blur alone washes the colour out of what
       stands behind the pane. */
    --card-radius: var(--radius-md);
    --card-blur: 15px;
    --card-saturate: 150%;
    --card-edge: inset 0 1px 0 rgba(255, 255, 255, .18);   /* the lit top edge of a pane */
    /* EVERY RECIPE NAMES ITS OWN SOLID VERSION OF ITSELF (`--card-solid`): the surface a person gets when they
       asked the system for less transparency, or when the browser cannot blur a backdrop at all. It is a token
       and not one fixed colour for the whole house because the three recipes are not the same material: a dark
       glass card and a warm clay tile cannot both be answered with the same fill - the first needs its own dark,
       the second its own cream. Measured 2026-10-01, the hard way: one dark fill for every card left the clay
       tile dark while its ink stayed dark too - a heading at 1.08:1, i.e. invisible, in both company areas. */
    --card-solid: #1b1e24;
    --section-alt: #15171c;   /* grey-black: breaks the monotony of the dark page */
    --header-bg: rgba(11, 10, 9, .35);
    --header-bg-solid: rgba(11, 10, 9, .9);
    --accent: #f3c14b;
    /* Aliases for the ported authentication and printer styles: they speak the older
       token names, these lines connect them to the current ones. */
    --brand-gold:     var(--accent);
    --brand-gold-2:   var(--accent-2);
    --brand-ink:      var(--page-ink);
    --brand-muted:    var(--muted);
    --brand-bg:       var(--page-bg);
    --brand-line:     var(--line);
    --brand-surface:  var(--card-bg);
    --accent-rgb:          243, 193, 75;   /* the same accent as RGB, so tints and glows follow it */
    --accent-2: #e0a327;
    --accent-ink: #231a06;
    --accent-soft:          rgba(var(--accent-rgb), .12);
    --accent-line:          rgba(var(--accent-rgb), .30);
    --glow:                 rgba(var(--accent-rgb), .28);
    --focus: #f3c14b;

    /* the light working area (back office preview, invoices, print) */
    --light-bg: #f6f7f9;
    --light-card: #ffffff;
    --light-ink: #101828;
    --light-muted: #667085;
    --light-line: #e4e7ec;
    --light-accent: #2563eb;
}

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

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

body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 1.6;
    color: var(--page-ink);
    background: var(--page-bg);
}

img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 { margin: 0 0 12px; font-family: var(--font-heading); line-height: 1.15; font-weight: 700; }
/* A heading is a line of thought, not a column: the browser is asked to even the lines out instead of leaving one
   word alone on the last line ("The papers you may ask for" ended with "for" on its own until 2026-10-01). A
   browser that does not know the rule simply wraps the old way - nothing breaks. */
h1, h2, h3, h4 { text-wrap: balance; }
p { margin: 0 0 14px; }
ul { margin: 0; padding: 0; list-style: none; }

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

.visually-hidden {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------- layout ---------------------------------- */
.wrap { width: min(100% - 40px, var(--wrap)); margin: 0 auto; }
.section { padding: 32px 0; }
.section-alt { background: var(--section-alt); }

/* ------------------------------- the clay recipe -----------------------------
   The two surfaces a COMPANY reads (its own area as a customer, and the partner company's area) carry the
   clay material: a WARM, OPAQUE surface that stands apart from the page (the owner's choice - warm cream
   in the brand, not a pastel that breaks the dark house), the widest radius of the system, a drop shadow
   cast to one side, and the two inner lights a pressed clay tile has - a bright one from the top left and a
   shadow from the bottom right. Both lights are OFFSET: a clay surface is modelled, not tinted, and a
   vertical-only highlight reads as a normal card (which is exactly what the first attempt looked like).
   The ink inside turns dark with the surface: the words must be readable on cream, and a control nested in
   a clay card is re-inked for the same reason - it is the surface that changed, not the control. */
body.area-customer, body.area-partner {
    --card-bg: #f4ecdd;
    --card-solid: #f4ecdd;   /* clay is opaque already: its own colour IS its solid version */
    --card-line: rgba(122, 94, 44, .20);
    --card-shadow: 8px 8px 26px rgba(0, 0, 0, .34),
                   inset -7px -7px 16px rgba(122, 94, 44, .18),
                   inset 7px 7px 18px rgba(255, 255, 255, .92);
    --card-radius: 30px;
    --card-blur: 0px;
    /* NOT `none`: the card's box-shadow is a LIST (`var(--card-edge), var(--card-shadow)`), and a `none`
       inside a list makes the whole declaration invalid - the shadow then disappears without a word. A
       transparent layer of the same shape is what says "no edge here". */
    --card-edge: 0 0 0 rgba(255, 255, 255, 0);
    --clay-ink: #2b2317;
    --clay-muted: #6f5f45;
    --section-alt: #14171d;
}
body.area-customer .card, body.area-partner .card { color: var(--clay-ink); }
body.area-customer .card h3, body.area-partner .card h3,
body.area-customer .card h2, body.area-partner .card h2 { color: var(--clay-ink); }
body.area-customer .card p, body.area-partner .card p,
body.area-customer .card .muted, body.area-partner .card .muted,
body.area-customer .card .small, body.area-partner .card .small { color: var(--clay-muted); }
body.area-customer .card .card-mark, body.area-partner .card .card-mark {
    color: #7a5a12; background: rgba(243, 193, 75, .28); border-color: rgba(122, 90, 18, .35);
}
/* A control inside a clay card: the same shape, inked for the surface under it. */
body.area-customer .card .btn-ghost, body.area-partner .card .btn-ghost {
    color: var(--clay-ink); border-color: rgba(43, 35, 23, .28); background: rgba(255, 255, 255, .55);
}
body.area-customer .card .btn-ghost:hover, body.area-partner .card .btn-ghost:hover {
    background: rgba(255, 255, 255, .85); border-color: rgba(43, 35, 23, .40);
}
body.area-customer .card input, body.area-partner .card input,
body.area-customer .card select, body.area-partner .card select,
body.area-customer .card textarea, body.area-partner .card textarea {
    color: var(--clay-ink); border-color: rgba(43, 35, 23, .22); background: rgba(255, 255, 255, .60);
}
/* Clay does not lift like glass - it BOUNCES, and it presses when it is touched. */
body.area-customer .card, body.area-partner .card { transition: transform .2s cubic-bezier(.34, 1.56, .64, 1), box-shadow .2s ease; }
body.area-customer .card:hover, body.area-partner .card:hover {
    transform: translateY(-5px) scale(1.01);
    box-shadow: 10px 12px 30px rgba(0, 0, 0, .38),
                inset -7px -7px 18px rgba(122, 94, 44, .20),
                inset 7px 7px 18px rgba(255, 255, 255, .95);
}

/* ---------------------------- the quiet recipe (the worker's tool) -----------
   The employee's area is not read at a desk: it is read on a phone, at six in the morning, in a stairwell,
   with one hand. So it carries neither glass nor clay - no blur to compute on a cheap phone, no soft shadow
   to hide an edge: a solid surface with a crisp line. Same grammar, material turned down. The ONE place a
   moulded surface belongs here is the button that starts and ends a shift: it is pressed, by a thumb, and
   the press can be seen (a neumorph control - surface of its own colour, a light and a dark shadow, and the
   two of them swap when the thumb goes down). */
body.area-staff {
    --card-bg: #191c22;
    --card-solid: #191c22;   /* the quiet surface is solid by design, so its solid version is itself */
    --card-line: rgba(255, 255, 255, .10);
    --card-shadow: 0 2px 0 rgba(0, 0, 0, .25);
    --card-radius: var(--radius-md);
    --card-blur: 0px;
    --card-edge: 0 0 0 rgba(255, 255, 255, 0);
}
/* The one moulded surface in the worker's area: the button that starts and ends a shift. Pressed by a
   thumb, so the press can be seen - the light and the dark shadow swap places when it goes down.
   `.btn.btn-shift` and not `.btn-shift`: the amber primary button is defined further down in this file and
   would win the plain selector (found by measuring, not by reading: the first attempt kept the amber glow
   and the pill radius and looked like nothing had happened). */
.btn.btn-shift {
    background: #1f232a; color: var(--page-ink);
    border: 1px solid rgba(255, 255, 255, .06);
    border-radius: 18px;
    box-shadow: 7px 7px 16px rgba(0, 0, 0, .55), -5px -5px 14px rgba(255, 255, 255, .05);
    padding: 18px 30px; font-size: 17px; min-height: 58px;
    transition: box-shadow .14s ease;
}
.btn.btn-shift:hover { transform: none; filter: none; background: #232830; }
.btn.btn-shift:active {
    box-shadow: inset 6px 6px 14px rgba(0, 0, 0, .6), inset -4px -4px 12px rgba(255, 255, 255, .05);
}
.section-head { max-width: 760px; margin-bottom: 20px; }
.eyebrow {
    display: inline-block; margin-bottom: var(--space-3);
    font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
    color: var(--accent-text);
}
.display { font-size: clamp(32px, 5vw, 56px); letter-spacing: -.5px; }
.lead { font-size: clamp(16px, 1.6vw, 19px); color: var(--muted); max-width: 60ch; }
.muted { color: var(--muted); }
.small { font-size: 13.5px; }

.alert { border-radius: var(--radius-sm); padding: 12px 14px; margin-bottom: var(--space-5); font-size: 15px; }
.alert-ok { background: rgba(21, 128, 61, .16); border: 1px solid rgba(21, 128, 61, .45); color: #cdf3d8; }
.alert-error { background: rgba(220, 80, 80, .14); border: 1px solid rgba(220, 80, 80, .45); color: #ffd9d9; }

/* ---------------------------------- header ---------------------------------- */
.site-header {
    position: sticky; top: 0; z-index: 60;
    background: var(--header-bg);
    border-bottom: 1px solid transparent;
    backdrop-filter: blur(12px) saturate(130%);
    transition: background .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.site-header.is-scrolled {
    background: var(--header-bg-solid);
    border-bottom-color: var(--line);
    box-shadow: 0 10px 30px rgba(0, 0, 0, .25);
}
.header-inner { display: flex; align-items: center; gap: var(--space-5); padding: 14px 0; }
.brand { display: flex; align-items: center; gap: 10px; font-weight: 800; }
.brand img { height: 34px; width: auto; }

.nav { display: flex; align-items: center; gap: var(--space-5); margin-left: auto; }
.nav-link { font-size: 15px; opacity: .88; position: relative; padding: 6px 0; }
.nav-link:hover { opacity: 1; }
.nav-link[aria-current="page"] { opacity: 1; font-weight: 600; }
.nav-link[aria-current="page"]::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
    background: var(--accent); border-radius: 2px;
}
.header-actions { display: flex; align-items: center; gap: var(--space-3); }
.lang-switch { display: flex; gap: 2px; font-size: 12px; letter-spacing: .1em; }
.lang-switch a { padding: 4px 7px; border-radius: var(--radius-sm); opacity: .7; }
.lang-switch a:hover { opacity: 1; }
.lang-switch a[aria-current="true"] { opacity: 1; background: rgba(255, 255, 255, .14); }

/* The menu button. It carries the same three lines a visitor knows from every other site and
   turns into a cross while the panel is open; it only exists where the wide menu does not. */
.nav-toggle {
    display: none; width: 44px; height: 40px; padding: 0; cursor: pointer;
    align-items: center; justify-content: center; flex-direction: column; gap: 5px;
    border: 1px solid var(--line); border-radius: var(--radius-sm);
    background: transparent; color: var(--page-ink);
}
.nav-toggle span {
    display: block; width: 20px; height: 2px; border-radius: 2px;
    background: currentColor; transition: transform .22s ease, opacity .18s ease;
}
.nav-toggle:hover { border-color: var(--accent-text); color: var(--accent-text); }
.nav-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* --------------------------------- buttons ---------------------------------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    padding: 13px 22px; border-radius: var(--radius-pill); border: 1px solid transparent;
    font: inherit; font-weight: 600; cursor: pointer;
    transition: transform .15s ease, filter .15s ease, background .2s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn-primary {
    background: linear-gradient(180deg, var(--accent), var(--accent-2));
    color: var(--accent-ink);
    box-shadow: 0 12px 26px var(--glow), inset 0 1px 0 rgba(255, 255, 255, .45);
}
.btn-ghost { border-color: var(--line); color: inherit; background: transparent; }
.btn-ghost:hover { background: rgba(255, 255, 255, .08); }
.btn-sm { padding: 9px 16px; font-size: 14px; }

/* ----------------------------------- hero ----------------------------------- */
/* The film runs BEHIND the promise: the hero is the box, the film fills it, a scrim keeps the text
   readable, and the words stand above both. The poster is the background of the box as well, so a
   browser that cannot play the film (or a person who asked for less movement) sees the picture and
   not a black hole. */
.hero {
    position: relative;
    overflow: hidden;
    /* THE WORDS STAND BELOW THE FILM (the owner's word, 2026-10-01: *"let us put the text under the video"*), so
       the hero is no longer a full-height stage with the film behind everything: it is a FILM BAND with the words
       under it. The band keeps the picture - it is what the house is showing - and the words get the page's own
       surface and the page's own ink. Nothing is laid over the film at all any more. */
    display: block;
    min-height: 0;
    padding: 0 0 var(--space-8);
}
/* The film and its control: the stage carries the height and the shape, the film fills it, the control sits in
   its own corner.
   THE BAND CARRIES THE FILM'S OWN SHAPE (16:9, measured from the file itself: 1024x576), because a band of any
   other shape CROPS the picture: the first attempt was a 42vh strip, and with `object-fit: cover` that showed a
   letterbox of the middle of the frame - the owner's word for it was *"the video is extremely shortened - it
   cannot be seen"*, and he was right. With the shape of the film, what is on the screen is what is in the file.
   The only cap is the screen itself (86vh): on a laptop that trims about a twentieth of the height, and on a
   phone the band is simply 16:9 of the width. */
.hero-stage {
    position: relative;
    z-index: 1;
    width: 100%;
    aspect-ratio: 16 / 9;
    max-height: 86vh;
    overflow: hidden;
}
.hero-streaks { position: absolute; inset: -25%; z-index: 0; pointer-events: none; }
.hero-streaks {
    background:
        repeating-linear-gradient(115deg, rgba(255, 255, 255, .035) 0 2px, transparent 2px 9px),
        radial-gradient(110% 60% at 18% 8%, rgba(var(--accent-rgb), .30), transparent 55%),
        radial-gradient(90% 55% at 88% 88%, rgba(224, 163, 39, .22), transparent 60%),
        linear-gradient(160deg, #141210 0%, #0b0a09 46%, #171310 100%);
    animation: drift 26s ease-in-out infinite alternate;
}
@keyframes drift {
    from { transform: translate3d(-1.5%, -1%, 0) scale(1.03); }
    to   { transform: translate3d(1.5%, 1%, 0) scale(1.06); }
}
.hero-media {
    position: absolute;
    inset: 0;
    z-index: 1;
    overflow: hidden;
    background: #0b0a09 center / cover no-repeat;
}.hero-media video {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    background: transparent;
}
/* The film is CLEAN (the owner's word, 2026-10-01): there is no scrim over it any more. What used to be a
   dark veil on the picture is now a pane OF GLASS standing on it - the words live on a rounded glass card,
   and the film keeps every pixel it has. There is no `.hero-scrim` rule left: a veil that nothing wears is
   a rule that lies about the page. */
/* "What we clean", named in the hero too: a quiet strip under the buttons, separated by a hairline.
   Small type, five items that wrap, and the note under them. It shows the same texts as the section
   further down the page. */
.hero-scope {
    margin: 20px auto 0;
    padding-top: 20px;
    border-top: 1px solid rgba(255, 255, 255, .18);
    max-width: 820px;
}
.hero-scope-title {
    display: block;
    font-size: 11.5px;
    letter-spacing: .16em;
    text-transform: uppercase;
    font-weight: 700;
    color: var(--accent-text);
    margin-bottom: 10px;
}
.hero-scope-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 22px;
    justify-content: center;
}
.hero-scope-list li { position: relative; padding-left: 17px; font-size: 14px; color: #ded7ca; }
.hero-scope-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 7px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: linear-gradient(180deg, var(--accent), var(--accent-2));
}
.hero-scope-note { margin: 12px 0 0; font-size: 13px; color: #c9c0b2; }
/* On a phone the strip is the widest thing in the hero: it keeps the words, loses the row shape. */
@media (max-width: 760px) {
    .hero-scope { margin-top: var(--space-5); }
    .hero-scope-list { gap: 6px 16px; }
}
/* The one control the film has: stop it. A film that runs by itself for more than five seconds has to be
   stoppable (WCAG 2.2.2), and the audit of 2026-10-01 could not stop either film. It stands quietly in the
   corner of the hero, and it is never shown when no film runs - a person who asked for less movement sees
   no button at all. */
.hero-film-toggle {
    position: absolute;
    right: var(--space-4);
    bottom: var(--space-4);
    z-index: 4;
    width: 40px;
    height: 40px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, .30);
    background: rgba(11, 10, 9, .55);
    color: #f4efe6;
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    transition: border-color .18s ease, color .18s ease, background .18s ease;
}
.hero-film-toggle:hover,
.hero-film-toggle:focus-visible { border-color: var(--accent-text); color: var(--accent-text); background: rgba(11, 10, 9, .78); }
.hero-film-toggle[hidden] { display: none; }
.hero-film-toggle .is-play { display: none; }
.hero-film-toggle.is-paused .is-pause { display: none; }
.hero-film-toggle.is-paused .is-play { display: inline; }
@media (max-width: 760px) {
    .hero-film-toggle { right: var(--space-3); bottom: var(--space-3); width: 36px; height: 36px; }
}
/* The words stand on the page itself now, in the page's light ink: no rim, no shadow, nothing under or over
   them. (This block used to give dark letters a light edge while they stood on a white pane; the pane is gone.) */
.hero-copy .display,
.hero-copy .eyebrow,
.hero-copy .lead,
.hero-copy .hero-points,
.hero-copy .hero-scope {
    text-shadow: none;
}
/* Less movement asked for: the film stands still as its poster. */
@media (prefers-reduced-motion: reduce) {
    .hero-media video { visibility: hidden; }
    .hero-streaks { animation: none; }
}
/* On a phone the band follows the film's own shape like everywhere else (16:9 of the width): the picture stays
   whole, and the words under it are still on the first screen. */
@media (max-width: 760px) {
    .hero { padding: 0 0 var(--space-7); }
    .hero-copy { padding-top: var(--space-6); }
}
/* The `.liquid-glass` helper rule is gone with the glass it hid: no page prints those definitions any more (see
   the note further down), and a rule nothing wears is a rule that lies about the page. The definitions carried
   `width="0" height="0"` themselves, so the day they return they need nothing from this file. */
/* THE WORDS STAND ON NOTHING AT ALL (the owner's word, 2026-10-01, the third correction of that day):
   *"no - take the glass off the hero at the video completely - leave only a transparent square as it was - I want
   the video to be seen - this way it does not please me."*
   So there is NO fill, NO edge, NO drop, NO blur, NO bend and NO halo: nothing at all stands between the words and
   the film. The square stays a PLACE - the words keep their width and their rounded place - and it is transparent,
   which is the whole of it. What carries the words is the FILM ITSELF, and that is measured rather than hoped: the
   picture behind this block is a bright wall (126-137 of 255 on every frame of it) where the dark ink measures
   4.6:1 or better, which is why the ink here is dark and not the white that was set by hand on the live file
   (white on this film measures about 2.6:1). The proof holds that number on the film's DARKEST frame.
   NOTHING OF THIS PANE ANSWERS ANY SETTING: there is no translucency to reduce, no blur to drop and no fill to
   make solid, so a person who asks their system for less transparency gets exactly this - proved.
   THE BEND IS PUT AWAY, NOT DELETED: the liquid glass of step 91 stands ready and un-worn (see the note below). */
/* THE WORDS STAND UNDER THE FILM (the owner's word, 2026-10-01, the fourth correction of that day):
   *"let us put the text under the video."*
   So the pane - filled, frosted, bent or transparent - is gone entirely: it is not a surface and not even a place
   over the picture any more. The film is a clean band at the top of the page, and the words stand BELOW it, on
   the page's own background, in the page's own ink. That is why the inks here are the PAGE's (light words on the
   dark house) and not the dark ones they had to be while they stood on a bright film: `--pane-ink` now points at
   `--page-ink`, `--pane-muted` at `--muted`, `--pane-amber` at `--accent`. The amber is allowed to be text again,
   because it now stands on the house's dark ground where it measures well, and the dots take it directly.
   Nothing is laid over the film: no fill, no blur, no bend, no halo - the picture is whole. */
.hero-copy {
    position: relative;
    z-index: 3;
    max-width: 900px;
    margin: 0 auto;
    text-align: center;
    padding: var(--space-7) clamp(20px, 3vw, 48px) 0;
    background: transparent;
    border: none;
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    text-shadow: none;
    color: var(--page-ink);
    --pane-ink: var(--page-ink);
    --pane-muted: var(--muted);
    --pane-amber: var(--accent);
    --pane-dot: var(--accent);
    --pane-line: var(--line);
}
/* THE LIQUID GLASS IS NOT WORN AT ALL (the owner's word, 2026-10-01: the words left the film). The machinery
   stands ready - `partials/liquid-glass.php`, `tools/make-liquid-glass-map.js` and the map in
   `assets/liquid-glass-map.png` - and its story, its numbers and the mistakes it was first got wrong by stand in
   step 91 of the diary. Nothing declares it: a rule nothing wears is a rule that lies about the page, and there is
   no pane over the picture left for a bend to be seen through. The two pane fallbacks are gone for the same
   reason - the words are not on a translucent surface any more, so `prefers-reduced-transparency` and a browser
   without backdrop blur change nothing about them (the CARDS still answer with their own solids, below). */
.hero-copy .display {
    color: var(--pane-ink);
    /* No halo, no line, no shadow: the words stand on the page's own ground (his word of the day). */
    text-shadow: none;
}
.hero-copy .eyebrow { color: var(--pane-amber); }
.hero-copy .lead { color: var(--pane-muted); margin-left: auto; margin-right: auto; }
.hero-copy .hero-points li { color: var(--pane-muted); }
.hero-copy .hero-points li::before { background: var(--pane-dot); }
.hero-copy .hero-scope { border-top-color: var(--pane-line); }
.hero-copy .hero-scope-title { color: var(--pane-amber); }
.hero-copy .hero-scope-list li { color: var(--pane-muted); }
.hero-copy .hero-scope-list li::before { background: var(--pane-dot); }
.hero-copy .hero-scope-note { color: var(--pane-muted); }
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: center; margin: var(--space-5) 0 0; }
.trust {
    display: flex; flex-wrap: wrap; gap: var(--space-5); justify-content: center;
    padding: var(--space-5) 0 var(--space-6);
    font-size: 13.5px; color: var(--muted);
}
.trust span { display: inline-flex; align-items: center; gap: 7px; }
.trust b { color: inherit; }

/* ---------------------------------- cards ----------------------------------- */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: var(--space-5); }
.card {
    padding: var(--space-5); border-radius: var(--card-radius);
    background: var(--card-bg); border: 1px solid var(--card-line); box-shadow: var(--card-edge), var(--card-shadow);
    -webkit-backdrop-filter: blur(var(--card-blur)) saturate(var(--card-saturate));
    backdrop-filter: blur(var(--card-blur)) saturate(var(--card-saturate));
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
/* A browser that cannot blur the backdrop gets a surface it can still read the words on - the fill first,
   the see-through version only where the blur is really available (the advice MDN and every glass guide
   gives, and the reason a glass panel is legible on an old browser instead of a smudge). */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .card { background: rgba(255, 255, 255, .09); }
}
/* A person who asked the system for less transparency gets a solid surface and no blur - EACH RECIPE'S OWN
   SOLID, never one colour for the whole house. The tint is what carries the readability, so it goes up when the
   blur goes away; but a warm clay tile whose ink is dark must not be handed the dark glass fill, or the words
   on it disappear (measured: a heading at 1.08:1). The bug was born here and this is where it is buried. */
@media (prefers-reduced-transparency: reduce) {
    .card {
        background: var(--card-solid);
        -webkit-backdrop-filter: none; backdrop-filter: none;
    }
    /* THE HEADER OBEYS TOO. It was found ignoring the setting (measured 2026-10-01: rgba(11,10,9,.35) with
       blur(12px) in BOTH states): a person who asked their system for less transparency should not be handed
       the one surface that is always on the screen, blurred, over their own content. The solid header colour
       already exists for a scrolled header, so the answer costs nothing new. */
    .site-header {
        background: var(--header-bg-solid);
        -webkit-backdrop-filter: none; backdrop-filter: none;
    }
}
.card:hover { transform: translateY(-3px); border-color: var(--accent-line); }
.card h3 { font-size: 18px; }
.card p { margin: 0; color: var(--muted); font-size: 15px; }
.card-icon {
    width: 44px; height: 44px; border-radius: 12px; display: grid; place-items: center;
    margin-bottom: var(--space-4); color: var(--accent-text);
    background: var(--accent-soft); border: 1px solid var(--accent-line);
}
.card-icon svg { width: 22px; height: 22px; }

/* -------------------------------- calculator -------------------------------- */
.calculator {
    display: grid; grid-template-columns: 1.1fr .9fr; gap: var(--space-6);
    padding: var(--space-6); border-radius: var(--radius-lg);
    background: var(--card-bg); border: 1px solid var(--card-line); box-shadow: var(--card-shadow);
}
.field { margin-bottom: var(--space-5); }
.field label { display: block; font-size: 13.5px; font-weight: 600; margin-bottom: 6px; }
.field .hint { font-size: 12.5px; color: var(--muted); margin: 6px 0 0; }
.range { width: 100%; accent-color: var(--accent-text); }
.range-value { font-weight: 700; color: var(--accent-text); }
select,
input[type="text"],
input[type="email"],
input[type="tel"],
textarea {
    width: 100%; font: inherit; padding: 12px 14px; border-radius: var(--radius-sm);
    border: 1px solid var(--line); background: rgba(255, 255, 255, .04); color: var(--page-ink);
}
select option { background: #14120f; color: var(--page-ink); }
input::placeholder, textarea::placeholder { color: rgba(246, 242, 234, .4); }

.calc-result {
    display: flex; flex-direction: column; justify-content: center; gap: 6px;
    padding: var(--space-5); border-radius: var(--radius-md);
    background: linear-gradient(160deg, rgba(var(--accent-rgb), .16), rgba(var(--accent-rgb), .04));
    border: 1px solid var(--accent-line);
}
.calc-result .amount { font-family: var(--font-heading); font-size: clamp(30px, 4vw, 44px); font-weight: 800; }
.calc-result .note { font-size: 13px; color: var(--muted); }

/* ---------------------------------- about ----------------------------------- */
/* The film of this page stands in its HERO now, so the full-width film block is gone - the rules for
   it went with the last page that used it (owner's word, 2026-10-01: two films on one page are one too
   many). What is left of the old class is nothing, on purpose. */
.about-body {
    display: grid; grid-template-columns: 1.1fr .9fr; gap: var(--space-6);
    align-items: start; margin: 0 0 var(--space-5);
}
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.stat { padding: var(--space-4); border-radius: var(--radius-md); background: var(--card-bg); border: 1px solid var(--card-line); }
.stat b { display: block; font-family: var(--font-heading); font-size: 26px; }
.stat span { font-size: 13px; color: var(--muted); }

/* --------------------------------- contact ---------------------------------- */
.contact-strip {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-5);
    padding: var(--space-6); border-radius: var(--radius-lg);
    background: var(--card-bg); border: 1px solid var(--card-line); box-shadow: var(--card-shadow);
}
.contact-strip h2 { margin-bottom: 6px; }
.contact-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }

.inquiry-form {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4) var(--space-5);
    margin-top: var(--space-6); padding: var(--space-6); border-radius: var(--radius-lg);
    background: var(--card-bg); border: 1px solid var(--card-line); box-shadow: var(--card-shadow);
}
.inquiry-form .field { margin: 0; }
.inquiry-form .field-wide { grid-column: 1 / -1; }
.inquiry-form .actions { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--space-4); }
.required-mark { color: var(--accent-text); font-weight: 700; }

/* --------------------------- back office preview ----------------------------- */
.app-note {
    display: inline-flex; align-items: center; gap: 8px; margin-bottom: var(--space-4);
    padding: 6px 12px; border-radius: var(--radius-pill);
    background: rgba(37, 99, 235, .12); border: 1px solid rgba(37, 99, 235, .35);
    color: #9dc0ff; font-size: 13px; font-weight: 600;
}
.app-window {
    border-radius: var(--radius-lg); overflow: hidden; background: var(--light-card); color: var(--light-ink);
    border: 1px solid var(--light-line); box-shadow: 0 20px 50px rgba(0, 0, 0, .45);
}
.app-topbar {
    display: flex; align-items: center; gap: var(--space-4);
    padding: 12px 18px; border-bottom: 1px solid var(--light-line); background: #fbfcfe;
}
.app-topbar .app-brand { font-weight: 800; color: var(--light-ink); }
.app-nav { display: flex; gap: var(--space-4); font-size: 14px; color: #475467; }
.app-nav .is-active { color: var(--light-ink); font-weight: 600; border-bottom: 2px solid var(--light-accent); }
.app-user { margin-left: auto; font-size: 13px; color: var(--light-muted); }
.app-body { padding: var(--space-5); background: var(--light-bg); }
.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--space-4); margin-bottom: var(--space-5); }
.kpi { padding: var(--space-4); border-radius: 10px; background: var(--light-card); border: 1px solid var(--light-line); }
.kpi span { display: block; font-size: 12.5px; color: var(--light-muted); }
.kpi b { font-size: 24px; font-weight: 800; }

table.data { width: 100%; border-collapse: collapse; font-size: 14px; }
table.data th, table.data td { text-align: left; padding: 11px 14px; border-bottom: 1px solid #eef1f5; white-space: nowrap; }
table.data th { background: #fbfcfe; font-size: 12.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--light-muted); }
table.data td.num { text-align: right; font-variant-numeric: tabular-nums; }
.badge { display: inline-block; padding: 3px 10px; border-radius: var(--radius-pill); font-size: 12px; font-weight: 600; }
.badge-paid { background: #e7f6ec; color: #15803d; }
.badge-open { background: #fef3e2; color: #b45309; }

/* A chip: one short word standing where a value would be (a draft has no number yet). It takes no
   depth recipe - it is a word, not a surface. */
.chip {
    display: inline-block; padding: 2px 8px; border-radius: var(--radius-pill);
    border: 1px solid var(--line); font-size: 12px; font-weight: 600; letter-spacing: .02em;
    color: var(--muted); text-transform: none;
}

/* The toast: the answer to a small, reversible save. It stands at the top, it leaves by itself, and it
   carries the way back. A save about money or a document does NOT use this - it gets the block that stays
   (the rule, and the reason for it, stand in `partials/feedback.php`). */
.toast {
    position: fixed; z-index: 60; top: 18px; left: 50%; transform: translateX(-50%);
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    max-width: min(680px, calc(100vw - 32px)); padding: 11px 18px;
    border: 1px solid var(--accent); border-radius: var(--radius-pill);
    background: var(--section-alt); color: var(--page-ink);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .45);
    transition: opacity .35s ease, transform .35s ease;
}
.toast.is-gone { opacity: 0; transform: translateX(-50%) translateY(-10px); }
.toast-text { font-size: 14px; }
.toast-undo { margin: 0; }
@media (prefers-reduced-motion: reduce) { .toast { transition: none; } }

/* ---------------------------------- footer ---------------------------------- */
.site-footer {
    margin-top: var(--space-8); padding: var(--space-7) 0 var(--space-5);
    border-top: 1px solid var(--line); background: var(--section-alt);
}
.footer-cols { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: var(--space-6); }
.footer-col h3 { font-size: 14px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); font-family: var(--font-sans); }
.footer-col li { margin-bottom: 8px; font-size: 15px; }
.footer-col a:hover { color: var(--accent-text); }
.footer-col .soon { color: rgba(169, 159, 146, .75); font-size: 13px; }
.footer-bottom {
    display: flex; flex-wrap: wrap; gap: var(--space-4); justify-content: space-between;
    margin-top: var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--line);
    font-size: 13px; color: var(--muted);
}

/* ------------------------------- responsive --------------------------------- */
@media (max-width: 980px) {
    .calculator, .about-body, .inquiry-form { grid-template-columns: 1fr; }
    .footer-cols { grid-template-columns: 1fr 1fr; }
    /* The header itself is written at the end of this file: below 980px the menu folds into
       the panel behind the three-line button. */
}
@media (max-width: 620px) {
    .section { padding: 32px 0; }
    .footer-cols { grid-template-columns: 1fr; }
    .stats { grid-template-columns: 1fr 1fr; }
    /* Signing in stays on a phone: it is exactly what a visitor needs there. It only becomes
       smaller, so the mark, the button and the menu button share one line. */
    .header-actions { gap: var(--space-2); }
    .header-actions .btn { padding: 8px 12px; font-size: 13px; }
    .nav-toggle { width: 40px; }
    .brand img { height: 30px; }
}

/* The mark is nearly square (530 x 415), so its height decides its width. Declared sizes in the
   pages carry the true ratio; this keeps it right even when a page forgets them. */
.brand img { height: 34px; width: auto; display: block; }

/* ------------------------------- to the top --------------------------------- */
/* The button is in the page from the first moment and shows itself once the page is scrolled. */
.to-top {
    position: fixed; right: 18px; bottom: 18px; z-index: 80;
    display: none; align-items: center; gap: 8px;
    padding: 10px 15px; border-radius: 999px; cursor: pointer;
    border: 1px solid var(--line); background: var(--section-alt); color: var(--page-ink);
    font: inherit; font-size: 13px; box-shadow: 0 12px 32px rgba(0, 0, 0, .5);
}
.to-top.is-shown { display: inline-flex; }
.to-top:hover, .to-top:focus-visible { border-color: var(--accent-text); color: var(--accent-text); }
@media print { .to-top { display: none !important; } }

/* Motion is optional. */
@media (prefers-reduced-motion: reduce) {
    * { animation: none !important; transition: none !important; }
    html { scroll-behavior: auto; }
}

/* ------------------------------- the little robot -------------------------- */
/* A small 3D creature that appears once the film has been scrolled past, hovers in the corner and offers the
   way back up. It is decoration and says so: `aria-hidden`, no text hangs on it, and without JavaScript the
   page stands exactly as it always did. The heavy part (three.js, the model) never comes to a phone or to a
   device that asks for less motion - `assets/robot-boot.js` decides that in a kilobyte. */
.robot-corner {
    position: fixed; right: 12px; bottom: 12px; z-index: 79;
    width: clamp(280px, 27vw, 380px); aspect-ratio: 1 / 1;
    opacity: 0; transform: translateY(26px) scale(.94);
    transition: opacity .6s ease, transform .6s cubic-bezier(.22, .61, .36, 1), filter .6s ease;
    filter: blur(4px) brightness(.55);            /* it comes from BEHIND the glass */
    pointer-events: none;
    /* Ein weicher dunkler Schein unter dem Wesen: die Seite dahinter wechselt ihre Farbe (Band, Karte, Grund),
       und ohne ihn verschwindet der dunkle Koerper auf dem einen und schwimmt auf dem anderen. */
    background: radial-gradient(closest-side, rgba(8, 9, 11, .55), rgba(8, 9, 11, 0) 72%);
}
.robot-corner.is-in { opacity: 1; transform: none; filter: none; }
.robot-corner.is-away { opacity: 0; transform: translateY(-42px) scale(1.04); filter: blur(3px); }
.robot-corner canvas { display: block; width: 100%; height: 100%; }
/* The button sits OVER the creature and is invisible: a click on the robot is the way back up, and a screen
   reader finds a real button with a real name. */
.robot-corner .robot-top {
    position: absolute; inset: 16% 16% 6% 16%; margin: 0; padding: 0; border: 0; border-radius: 50%;
    background: transparent; cursor: pointer; pointer-events: auto;
}
.robot-corner .robot-top:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
/* Solange das Wesen da ist, ist ES der Knopf: zwei Bedienelemente mit derselben Aufgabe im selben Eck sind
   eines zu viel. Faellt das Wesen aus (kein JavaScript, kein Modell, zu kleines Fenster), bleibt der Knopf
   der Seite genau wie er war - `has-robot` setzt nur, wer das Wesen wirklich geladen hat. */
body.has-robot .to-top { display: none !important; }
@media print { .robot-corner { display: none !important; } }
/* No phone, no touch screen, no narrow window: nothing to see, and nothing is downloaded either. */
@media (pointer: coarse), (max-width: 900px) { .robot-corner { display: none; } }

/* ---------------------------- added for the English site --------------------------- */
.hero-points { display: flex; flex-wrap: wrap; gap: 10px 24px; justify-content: center; margin: var(--space-5) 0 0; }
.hero-points li { position: relative; padding-left: 20px; font-size: 14.5px; color: var(--muted); }
.hero-points li::before { content: ""; position: absolute; left: 0; top: 8px; width: 8px; height: 8px; border-radius: 50%;
    background: linear-gradient(180deg, var(--accent), var(--accent-2)); }
.card-mark { display: inline-block; margin-bottom: 10px; padding: 3px 10px; border-radius: var(--radius-pill);
    background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--accent-text);
    font-size: 11.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.cards-three .card { text-align: center; }
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 20px; }
.step { position: relative; padding: 20px; border-radius: var(--radius-md);
    background: var(--card-bg); border: 1px solid var(--card-line); box-shadow: var(--card-shadow); }
.step h3 { font-size: 17px; }
.step p { margin: 0; color: var(--muted); font-size: 15px; }
.step-number { display: grid; place-items: center; width: 34px; height: 34px; margin-bottom: 14px; border-radius: 50%;
    background: linear-gradient(180deg, var(--accent), var(--accent-2)); color: var(--accent-ink); font-weight: 800; }
.note { margin-top: var(--space-5); padding: 12px 16px; border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, .05); border: 1px solid var(--line); color: var(--muted); font-size: 14px; }
.two-col { display: grid; grid-template-columns: 1.05fr .95fr; gap: 20px; align-items: start; }
/* Two separate blocks in ONE row (the owner's order, 2026-10-15): "Who we are" and "When the
   cleaning fails" were two stacked full-width bands with a lot of air between them. They are now
   two cards side by side, each carrying its own heading, and they fold to one column on a phone. */
.duo { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: stretch; }
.duo > .card { padding: 20px; }
.duo > .card > :first-child { margin-top: 0; }
.duo > .card > :last-child { margin-bottom: 0; }
@media (max-width: 760px) { .duo { grid-template-columns: 1fr; } }
.check-list li { position: relative; padding: 10px 0 10px 30px; border-bottom: 1px solid var(--line); font-size: 15.5px; }
.check-list li:last-child { border-bottom: 0; }
.check-list li::before { content: "\2713"; position: absolute; left: 0; top: 10px; color: var(--accent-text); font-weight: 800; }
.faq { display: grid; gap: var(--space-4); }
.faq details { padding: var(--space-4) var(--space-5); border-radius: var(--radius-md);
    background: var(--card-bg); border: 1px solid var(--card-line); }
.faq summary { cursor: pointer; font-weight: 600; }
.faq p { margin: 10px 0 0; color: var(--muted); }
table.prices { width: 100%; border-collapse: collapse; font-size: 15px; }
table.prices th, table.prices td { text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--line); }
table.prices th { color: var(--accent-text); font-size: 12.5px; letter-spacing: .06em; text-transform: uppercase; }
table.prices td.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.legal p, .legal li { font-size: 15.5px; color: var(--muted); }
.legal h2 { margin-top: var(--space-6); }
.legal ul { padding-left: 20px; list-style: disc; }
.legal li { margin-bottom: 6px; }
.result-breakdown { display: grid; gap: 8px; margin: 12px 0; }
.result-breakdown div { display: flex; justify-content: space-between; gap: 16px; font-size: 15px; }
.result-breakdown .sum { border-top: 1px solid var(--accent-line); padding-top: 8px; font-weight: 700; }
@media (max-width: 980px) { .two-col { grid-template-columns: 1fr; } }

/* ------------------------- tables on the dark pages -------------------------------- */
.table-dark { overflow: auto; border-radius: var(--radius-md); background: rgba(255, 255, 255, .035); border: 1px solid var(--line); }
table.prices td { color: var(--page-ink); }
table.prices tbody tr:hover { background: rgba(255, 255, 255, .03); }
table.facts { width: 100%; border-collapse: collapse; font-size: 15px; }
table.facts th { text-align: left; padding: 18px 14px; width: 46%; color: var(--muted); font-size: 12.5px;
    letter-spacing: .05em; text-transform: uppercase; border-bottom: 1px solid var(--line); vertical-align: top; }
table.facts td { padding: 18px 14px; border-bottom: 1px solid var(--line); color: var(--page-ink); }
table.facts tr:last-child th, table.facts tr:last-child td { border-bottom: 0; }

/* --------------------------- the mini receipt printer ------------------------------ */
.printer-stage { position: relative; display: flex; flex-direction: column; align-items: center; padding-top: var(--space-4); }
.printer {
    position: relative; z-index: 3;
    width: min(430px, 88vw); height: 54px;
    border-radius: 18px 18px 14px 14px;
    background: linear-gradient(180deg, #2b2d33, #14151a);
    box-shadow: 0 16px 34px rgba(0, 0, 0, .55), inset 0 1px 0 rgba(255, 255, 255, .14);
}
.printer::before {
    content: ""; position: absolute; left: 6%; right: 6%; bottom: 9px; height: 8px; border-radius: 6px;
    background: #07080a; box-shadow: inset 0 2px 6px rgba(0, 0, 0, .9);
}
.printer::after {
    content: ""; position: absolute; left: 50%; bottom: -7px; transform: translateX(-50%);
    width: 72%; height: 12px; border-radius: 50%;
    background: radial-gradient(closest-side, rgba(255, 96, 64, .38), transparent 76%);
    filter: blur(4px); opacity: .9;
}
.printer.busy { animation: printer-shake .28s ease 3; }
@keyframes printer-shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-1.5px); } 75% { transform: translateX(1.5px); } }

/* the paper clip: its height grows so the receipt looks like it is rolling out */
.paper-clip { position: relative; z-index: 2; width: min(370px, 82vw); overflow: hidden; height: 0; }
.paper-clip.rolling { transition: height .95s cubic-bezier(.2, .9, .15, 1); }

.paper {
    position: relative;
    margin-top: -6px;
    padding: var(--space-5) var(--space-5) var(--space-6);
    background: #fdf8ec; color: #14120f;
    font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
    font-size: 12.5px; line-height: 1.6;
    box-shadow: 0 22px 46px rgba(0, 0, 0, .40);
    /* torn bottom edge */
    -webkit-mask-image: radial-gradient(circle at 6px 100%, transparent 6px, #000 6.5px);
    mask-image: radial-gradient(circle at 6px 100%, transparent 6px, #000 6.5px);
    -webkit-mask-size: 12px 100%; mask-size: 12px 100%;
    -webkit-mask-repeat: repeat-x; mask-repeat: repeat-x;
    -webkit-mask-position: bottom; mask-position: bottom;
}
.paper h3 { margin: 0 0 var(--space-2); font-family: var(--font-sans); font-size: 15px; letter-spacing: .04em; color: #0d0c0a; font-weight: 800; }
.paper .shop { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-3); }
.paper .shop-sub { font-size: 11.5px; color: #4d4a43; }
.paper .shop-meta { text-align: right; font-size: 11.5px; color: #4d4a43; }
.paper .total { font-family: var(--font-sans); font-size: 26px; font-weight: 800; margin: var(--space-2) 0; color: #0d0c0a; }
.paper table { width: 100%; border-collapse: collapse; font-size: 12.5px; color: #14120f; font-weight: 500; }
.paper table td { padding: 3px 0; border: 0; }
.paper table td.num { text-align: right; white-space: nowrap; }
.paper .line { border-top: 1px dashed #b9b2a1; margin: var(--space-3) 0; }
.paper .foot { text-align: center; color: #4d4a43; font-size: 11px; }
.paper .barcode { display: flex; gap: 1px; height: 42px; margin: var(--space-3) 0 4px; align-items: stretch; }
.paper .barcode span { background: #26241f; flex: 0 0 auto; }
.paper .barcode-label { text-align: center; font-size: 11px; letter-spacing: .18em; color: #3f3c36; font-weight: 600; }

/* the stamp */
.stamp {
    position: absolute; right: var(--space-4); top: 38%;
    padding: 5px 12px; border: 3px solid currentColor; border-radius: 8px;
    font-family: var(--font-sans); font-weight: 800; font-size: 15px; letter-spacing: .10em;
    opacity: 0; transform: rotate(-14deg) scale(1.7);
}
.stamp.ok { color: #15803d; }
.stamp.warn { color: #b45309; }
.paper-clip.stamped .stamp { animation: stamp-in .34s cubic-bezier(.2, .9, .2, 1) forwards; animation-delay: .85s; }
@keyframes stamp-in {
    from { opacity: 0; transform: rotate(-14deg) scale(1.7); }
    to { opacity: .94; transform: rotate(-14deg) scale(1); }
}
.printer-actions { display: flex; gap: var(--space-3); margin-top: var(--space-5); flex-wrap: wrap; justify-content: center; }
.printer-caption { text-align: center; margin-top: var(--space-5); }
.printer-caption h2 { color: #fff; }
.printer-caption p { color: var(--brand-muted); font-size: var(--text-sm); }

@media (prefers-reduced-motion: reduce) {
    .paper-clip { height: auto !important; }
    .paper-clip .paper { margin-top: 0; }
    .stamp { opacity: .94; transform: rotate(-14deg) scale(1); }
}
/* ------------------------- the gold line that flows between the links --------------- */
.nav { position: relative; }
.nav-line {
    position: absolute; bottom: 0; left: 0; width: 0; height: 2px; border-radius: 2px;
    background: linear-gradient(90deg, rgba(var(--accent-rgb), 0), var(--accent) 18%, var(--accent) 82%, rgba(var(--accent-rgb), 0));
    box-shadow: 0 0 12px rgba(var(--accent-rgb), .55);
    opacity: 0; pointer-events: none;
    /* water, not a jump: it leans in quickly and settles softly */
    transition: left .42s cubic-bezier(.18, .9, .2, 1.06), width .42s cubic-bezier(.18, .9, .2, 1.06), opacity .3s ease;
}
.nav-line.is-on { opacity: 1; }
.nav-link { transition: color .25s ease, opacity .25s ease, text-shadow .25s ease; }
.nav-link:hover, .nav-link.is-near {
    opacity: 1; color: var(--accent-text);
    text-shadow: 0 0 14px rgba(var(--accent-rgb), .55);
}
.nav-link[aria-current="page"]::after { display: none; }   /* the flowing line replaces the fixed bar */
@media (prefers-reduced-motion: reduce) { .nav-line { transition: none; } }

/* checkbox line in the forms */
.check-line { display: flex; align-items: center; gap: 10px; font-size: 15px; cursor: pointer; }
.check-line input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--accent-text); }
.check-line span { color: var(--page-ink); }

/* ---------------------------- motion (see assets/motion.js) ------------------------ */
.reading-progress {
    position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 90;
    transform: scaleX(0); transform-origin: 0 50%;
    background: linear-gradient(90deg, var(--accent-2), var(--accent));
    box-shadow: 0 0 10px rgba(var(--accent-rgb), .6);
    pointer-events: none;
}
.will-reveal { opacity: 0; transform: translateY(14px); }
.is-revealed {
    opacity: 1; transform: none;
    transition: opacity .7s cubic-bezier(.2, .9, .2, 1) var(--reveal-delay, 0ms),
                transform .7s cubic-bezier(.2, .9, .2, 1) var(--reveal-delay, 0ms);
}
@media (prefers-reduced-motion: reduce) {
    .will-reveal { opacity: 1; transform: none; }
    .reading-progress { display: none; }
}

.btn-primary { transition: transform .25s cubic-bezier(.2, .9, .2, 1), filter .15s ease; }

/* ------------------------------- the menu on a phone ------------------------------- */
/* Below 980px the five pages do not fit next to the mark, so they move into a panel that the
   three-line button opens. Same markup, same links, one menu - the wide bar simply hides the
   button and the panel returns to a row. This block stands last on purpose: it has to win
   over the wide-menu rules above it, which carry the same weight. */
@media (max-width: 980px) {
    .header-inner { flex-wrap: nowrap; gap: var(--space-3); }
    .header-actions { margin-left: auto; }
    .nav-toggle { display: inline-flex; }
    .nav {
        position: absolute; left: 0; right: 0; top: 100%;
        display: none; flex-direction: column; align-items: stretch; gap: 0;
        width: auto; margin-left: 0; overflow: visible;
        padding: var(--space-2) 20px var(--space-4);
        /* Opaque on purpose: the page slides under the panel, and a menu you can read the
           page through is a menu nobody can read. */
        background: var(--page-bg); border-bottom: 1px solid var(--line);
        box-shadow: 0 22px 46px rgba(0, 0, 0, .5);
    }
    .site-header.is-open { background: var(--page-bg); }
    .site-header.is-open .nav { display: flex; }
    .nav-line { display: none; }                       /* the flowing line belongs to the row */
    .nav-link {
        padding: 13px 0; font-size: 16px; white-space: normal;
        border-bottom: 1px solid var(--line);
    }
    .nav-link:last-child { border-bottom: 0; }
    .nav-link:hover, .nav-link.is-near { text-shadow: none; }
    .nav-link[aria-current="page"] { color: var(--accent-text); }
}

/* --------------------- the month of the plan (the employee's rota) --------------------- */
/* Seven squares in a row, Monday first, as a month is read here. A square carries the number of
   the day and, when the office set something, the short name of the kind of day with its colour
   as a small bar on the left. A day outside the month stays in the grid but steps back, so the
   weeks keep their shape and nobody has to count columns. */
.rota-month {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 6px;
}
.rota-head {
    padding: 0 4px 6px;
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--muted);
}
.rota-day {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-height: 88px;
    padding: 8px 9px;
    border: 1px solid var(--card-line);
    border-radius: var(--radius-sm);
    background: var(--card-bg);
}
.rota-day.is-outside { opacity: .34; }
.rota-day.is-today { border-color: var(--accent-line); box-shadow: inset 0 0 0 1px var(--accent-line); }
.rota-number { font-size: 12px; color: var(--muted); }
.rota-mark {
    padding-left: 7px;
    font-size: 13px;
    line-height: 1.25;
    overflow-wrap: anywhere;
}
@media (max-width: 760px) {
    .rota-month { gap: 4px; }
    .rota-day { min-height: 66px; padding: 5px 6px; }
    .rota-mark { font-size: 12px; }
}

/* ------------------------------ the app on the phone ------------------------------ */
/* The offer to keep the site on the home screen (bottom left, where the "to the top" button of the
   right side does not stand), and the quiet bar that says when the phone is offline and when it is
   back. Both are made by `assets/pwa.js` and both are absent until the browser offers them, so a
   visitor who wants nothing of this sees exactly the site as before. */
.pwa-install {
    position: fixed;
    left: 16px;
    bottom: 16px;
    z-index: 40;
    padding: 11px 16px;
    border: 1px solid var(--accent-line);
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: var(--accent-ink);
    font: 600 14px/1 var(--font-sans);
    cursor: pointer;
    box-shadow: 0 12px 30px rgba(0, 0, 0, .45);
}
.pwa-install:hover { filter: brightness(1.06); }

.pwa-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 45;
    padding: 10px 16px;
    background: rgba(11, 10, 9, .95);
    border-top: 1px solid var(--accent-line);
    color: var(--page-ink);
    font-size: 14px;
    text-align: center;
    transform: translateY(110%);
    transition: transform .25s cubic-bezier(.2, .9, .2, 1);
}
.pwa-bar.is-visible { transform: none; }

/* The two lists of the offline page. */
.offline-list { margin: 10px 0 0; padding-left: 18px; }
.offline-list li { margin-bottom: 6px; }

@media print {
    .pwa-bar, .pwa-install { display: none !important; }
}

/* =====================================================================================
   THE CRAFT LAYER — what makes it read as an expensive site (2026-10-08)

   WHY A LAYER AND NOT A REWRITE. Everything above is the house's own work and it stays
   readable. This block refines what a stranger sees in the first two seconds and what an
   office looks at all day. It overturns NO decision: direction A (dark, glass, amber)
   stands; the film stays CLEAN (no scrim, no veil - the owner's word of 2026-10-01); the
   words stay UNDER the film. What changes is the craft.

   Four things a page is judged by, in this order:
     1. the size and the calm of the headline        -> h1.display, .lead, .eyebrow
     2. the space around everything                  -> .section, .section-head, .wrap
     3. whether a number looks like a fact           -> .stat b, .card-mark
     4. whether a control looks pressable             -> .btn
   ===================================================================================== */

:root {
    /* AIR. A page a stranger calls expensive carries more of it than it needs. */
    --space-7: 56px;
    --space-8: 104px;
    --wrap: 1260px;

    /* ONE display scale, one number scale, one label. A page with three of each is a page
       that looks assembled; a page with one of each looks designed.

       THE OWNER'S CEILING (2026-10-08, his words): *"the header no bigger than 30, the
       headings than 20 and the text than 14 - this is too much."* A ceiling is what keeps a
       page a product and not a poster. Every size below is a clamp whose upper end is the
       ceiling, so a phone gets a smaller step of the SAME scale, never a different one.

       AND ONE DIAL THE OFFICE MAY TURN (his next order, the same day): every ceiling is
       `calc(<the house's own number> * var(--type-scale))`, and the office writes that ONE
       factor on `Settings -> Appearance`. The numbers stay here, in one place, exactly as
       they were; the factor comes from the database (`theme.type_scale`, `partials/theme.php`)
       and is never printed when it is 1, so an untouched house reads its own size. */
    --type-scale: 1;
    --type-hero: calc(30px * var(--type-scale));
    --type-page: calc(30px * var(--type-scale));   /* the office's own page title */
    --type-h1: calc(26px * var(--type-scale));
    --type-h2: calc(20px * var(--type-scale));
    --type-h3: calc(16px * var(--type-scale));
    --type-text: calc(14px * var(--type-scale));
    --type-small: calc(13px * var(--type-scale));
    --type-number: calc(30px * var(--type-scale));   /* .stat b, the estimate */
    --type-mark: calc(15px * var(--type-scale));     /* the counter on a card */
    --type-btn-sm: calc(13.5px * var(--type-scale));
    --display-tracking: -.012em;
    --label-size: calc(11px * var(--type-scale));
    --label-tracking: .2em;

    --card-radius: 16px;
    --card-pad: clamp(18px, 1.8vw, 24px);

    /* a shade more light in the muted ink: it is read on glass, and glass eats contrast */
    --muted: #b3a998;
}

/* ---------------------------------- 1. the headline --------------------------------- */
/* The h1 is the promise and it may be loud - up to the owner's ceiling of 30. A section
   heading is a signpost and stops at 20. The FIRST screen's promise is the one heading
   allowed to reach the top of that scale; an inner page's title ("About us", "Contact") is
   one step down, because a page that opens with three words must not open with a shout. */
h1.display {
    font-size: clamp(21px, 2.4vw, var(--type-h1));
    line-height: 1.2;
    letter-spacing: var(--display-tracking);
    font-weight: 700;
}
.hero-copy h1.display {
    font-size: clamp(23px, 3vw, var(--type-hero));
    line-height: 1.18;
}
/* THE OFFICE'S OWN TITLE follows the same dial. It carried a hard `font-size:34px` as an inline style until
   2026-10-08, which beat every rule of this file: the office ignored both the owner's ceiling of 30 and the
   scale above it. The class replaces that inline style in `admin/_header.php` and `partials/area.php`. */
h1.display.page-title {
    font-size: clamp(21px, 2.4vw, var(--type-page));
}
h2.display {
    font-size: clamp(17px, 1.8vw, var(--type-h2));
    line-height: 1.25;
    letter-spacing: -.008em;
    font-weight: 700;
}
.eyebrow,
.hero-scope-title {
    font-size: var(--label-size);
    letter-spacing: var(--label-tracking);
    font-weight: 650;
}
body { font-size: var(--type-text); }
.lead {
    font-size: var(--type-text);
    line-height: 1.62;
    max-width: 62ch;
}
.section-head { max-width: 760px; }

/* ---------------------------------- 2. the space ------------------------------------ */
.section { padding: 32px 0; }
.wrap { width: min(100% - 48px, var(--wrap)); }
/* The air belongs to the pages a stranger reads. The back office is a work tool: the same
   rhythm one step tighter, so a table and a form stay on one screen. The office is the page
   that carries the grouped menu (`.admin-menu`); where the browser cannot ask (`:has`), the
   office is merely roomier - nothing breaks. */
body:has(.admin-menu) .section { padding: 32px 0; }

/* ---------------------------------- 3. the surface ---------------------------------- */
.card {
    border-radius: var(--card-radius);
    padding: var(--card-pad);
    transition: transform .22s cubic-bezier(.2, .9, .2, 1), border-color .22s ease, box-shadow .22s ease;
}
.card:hover { transform: translateY(-2px); }
.card h3 {
    font-family: var(--font-heading);
    font-size: var(--type-h3);
    letter-spacing: -.006em;
    line-height: 1.3;
}
.card p { font-size: var(--type-text); line-height: 1.6; }
/* an icon is a chip, not a glyph floating in the corner: the tint is what makes a row of
   cards read as one family */
.card-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 46px; height: 46px;
    border-radius: 14px;
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    color: var(--accent-text);
    margin-bottom: var(--space-4);
}

/* ---------------------------------- 4. the number ----------------------------------- */
/* A number is the one thing on a page that cannot be argued with, so it is set like a
   fact: serif, large, tight, on its own line, with its label under it. */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; }
.stat {
    background: none;
    border: 0;
    border-left: 1px solid var(--line);
    border-radius: 0;
    padding: 4px clamp(18px, 2.4vw, 38px) 0;
}
.stat:first-child { border-left: 0; padding-left: 0; }
.stat b {
    display: block;
    font-family: var(--font-heading);
    font-size: clamp(22px, 2.4vw, var(--type-number));
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    margin-bottom: 8px;
}
.stat span { font-size: var(--type-small); line-height: 1.55; color: var(--muted); }

/* the same treatment in the back office: the counter on a card is a number, not a badge */
.card-mark {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 30px; height: 30px; padding: 0 9px;
    border-radius: 9px;
    border: 1px solid var(--accent-line);
    background: var(--accent-soft);
    color: var(--accent-text);
    font-family: var(--font-heading);
    font-size: var(--type-mark); font-weight: 700; line-height: 1;
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------- 5. the control ---------------------------------- */
.btn { padding: 15px 28px; font-weight: 650; letter-spacing: .005em; }
.btn-primary { box-shadow: 0 14px 30px var(--glow), inset 0 1px 0 rgba(255, 255, 255, .5); }
.btn-primary:hover { filter: brightness(1.05); }
.btn-ghost { border-color: rgba(255, 255, 255, .22); }
.btn-sm { padding: 10px 18px; font-size: var(--type-btn-sm); }
/* the one invented number on the site (the estimate) is a number, so it obeys the same
   ceiling as a stat: it may be the largest figure on its screen and no larger than that */
.calc-result .amount { font-size: clamp(22px, 2.4vw, var(--type-number)); }

/* ---------------------------------- 6. the header and the footer -------------------- */
.header-inner { padding: 16px 0; }
.nav-link { font-size: var(--type-text); }
.site-footer { padding: var(--space-8) 0 var(--space-6); }

/* ---------------------------------- 7. the two things that shout -------------------- */
/* The film's own control and the invitation to keep the site on a phone were the loudest
   amber on the page - louder than the one button that earns money. Both keep their job
   and lose the shouting: glass and a hairline instead of a solid amber block. */
.pwa-install {
    background: rgba(11, 10, 9, .86);
    color: var(--page-ink);
    border-color: var(--line);
    backdrop-filter: blur(12px) saturate(140%);
    box-shadow: 0 10px 30px rgba(0, 0, 0, .4);
}
.pwa-install:hover { border-color: var(--accent-text); color: var(--accent-text); filter: none; }
.hero-film-toggle {
    border-color: var(--line);
    background: rgba(11, 10, 9, .55);
    backdrop-filter: blur(10px);
}

/* ---------------------------------- 8. a phone gets the calm version ---------------- */
@media (max-width: 760px) {
    :root { --space-8: 66px; }
    .stats { grid-template-columns: 1fr; gap: var(--space-5); }
    .stat { border-left: 0; padding-left: 0; }
    .stat + .stat { border-top: 1px solid var(--line); padding-top: var(--space-4); }
}



/* ===========================================================================================================
   THE SECOND ROW UNDER "SERVICES"  (the owner's order, 2026-10-15)
   "For hotels" and "For homes" stood beside "Services" as three equal things, although they are two rooms of
   the same house: a hotel and a private flat are the two ways a visitor arrives at the services page. They
   stand under it now. On a wide screen the row opens when the pointer or the keyboard reaches "Services"; in
   the folded menu of a phone it is simply there, indented, because a thing hidden behind a hover is a thing
   a finger never finds.
   =========================================================================================================== */

.nav-item { position: relative; display: flex; align-items: center; }
.nav-sub {
    position: absolute; top: calc(100% + 12px); left: 50%; transform: translateX(-50%);
    display: flex; flex-direction: column; gap: 2px; min-width: 200px; padding: 8px;
    border-radius: var(--radius-md);
    background: var(--page-bg); border: 1px solid var(--line);
    box-shadow: 0 20px 44px rgba(0, 0, 0, .45);
    opacity: 0; visibility: hidden;
    transition: opacity .18s ease, visibility .18s ease;
    z-index: 70;
}
/* A small pointer, so the row is visibly attached to the word above it. */
.nav-sub::before {
    content: ""; position: absolute; top: -6px; left: 50%; width: 10px; height: 10px;
    margin-left: -5px; transform: rotate(45deg);
    background: var(--page-bg); border-left: 1px solid var(--line); border-top: 1px solid var(--line);
}
.nav-item:hover .nav-sub,
.nav-item:focus-within .nav-sub { opacity: 1; visibility: visible; }
.nav-sub-link {
    padding: 9px 12px; border-radius: var(--radius-sm);
    font-size: 15px; opacity: .82; white-space: nowrap;
    transition: background .16s ease, opacity .16s ease;
}
.nav-sub-link:focus-visible { background: rgba(255, 255, 255, .07); opacity: 1; }
@media (hover: hover) and (pointer: fine) {
    .nav-sub-link:hover { background: rgba(255, 255, 255, .07); opacity: 1; }
}
.nav-sub-link[aria-current="page"] { opacity: 1; font-weight: 600; color: var(--accent-text); }

@media (max-width: 980px) {
    /* The folded menu is a column already: the second row needs no opening, only an indent. */
    .nav-item { display: block; position: static; }
    .nav-sub {
        position: static; transform: none; opacity: 1; visibility: visible;
        min-width: 0; padding: 0 0 4px 16px; gap: 0;
        background: transparent; border: 0; box-shadow: none;
    }
    .nav-sub::before { display: none; }
    .nav-sub-link { padding: 12px 0; font-size: 15.5px; opacity: .78; border-radius: 0; }
    .nav-sub-link + .nav-sub-link { border-top: 1px solid var(--line); }
    .nav-sub-link:hover, .nav-sub-link:focus-visible { background: transparent; opacity: 1; }
}


/* ===========================================================================================================
   THE LANGUAGE, FOLDED INTO ONE (the owner's order, 2026-10-15)
   "EN DE" asked for the width of two words to say one thing. On a 360px phone that width was the difference
   between a "Log in" button and a two-line circle, so the two stand in ONE control now: the letters of the
   language being read are the button, and the other one waits under it. Clicking opens it, because a phone
   has no hover; the keyboard reaches it without a line of script, because a `<details>` is a disclosure the
   browser already understands.
   =========================================================================================================== */

details.lang-switch { position: relative; display: block; }
.lang-switch > summary {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 9px; border-radius: var(--radius-sm); cursor: pointer;
    font-size: 12px; letter-spacing: .1em; opacity: .75; list-style: none;
}
/* The triangle the browser draws for a `<details>` is not this house's hand. */
.lang-switch > summary::-webkit-details-marker { display: none; }
.lang-switch > summary::marker { content: ""; }
.lang-switch[open] > summary { opacity: 1; background: rgba(255, 255, 255, .14); }
@media (hover: hover) and (pointer: fine) {
    .lang-switch > summary:hover { opacity: 1; background: rgba(255, 255, 255, .14); }
}
.lang-caret {
    width: 0; height: 0; opacity: .55;
    border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 4px solid currentColor;
    transition: transform .18s ease;
}
.lang-switch[open] .lang-caret { transform: rotate(180deg); }
.lang-menu {
    position: absolute; top: calc(100% + 10px); right: 0;
    display: flex; flex-direction: column; gap: 2px; min-width: 72px; padding: 6px;
    border-radius: var(--radius-md);
    background: var(--page-bg); border: 1px solid var(--line);
    box-shadow: 0 20px 44px rgba(0, 0, 0, .45);
    z-index: 70;
}
.lang-menu a {
    padding: 8px 11px; border-radius: var(--radius-sm); opacity: .8;
    font-size: 12px; letter-spacing: .1em; text-align: center;
}
.lang-menu a:focus-visible { background: rgba(255, 255, 255, .07); opacity: 1; }
@media (hover: hover) and (pointer: fine) {
    .lang-menu a:hover { background: rgba(255, 255, 255, .07); opacity: 1; }
}


/* ===========================================================================================================
   THE NARROWEST HEADER (2026-10-15)
   At 360px the row had to carry the mark, the weather, the language, the sign-in and the menu, and "Log in"
   broke onto two lines and became a circle: the button that earns money, made unreadable by the weather.
   Folding the two languages into one gave back a third of what was needed; this gives back the rest by
   asking every part to be a little smaller, so NOTHING has to be taken away. The weather keeps its number -
   it is the one place a visitor checks the day before booking a site visit.
   =========================================================================================================== */
@media (max-width: 400px) {
    .header-inner { gap: 6px; }
    .header-actions { gap: 5px; }
    .header-actions .btn { padding: 7px 10px; font-size: 12.5px; }
    .wx-pill { padding: 4px 8px; gap: 5px; }
    .wx-glyph { width: 18px; height: 18px; }
    .wx-temp { font-size: 13.5px; }
    .wx-caret { display: none; }        /* the chevron says "there is more" - the number already says the day */
}


/* ===========================================================================================================
   THE LIGHT SIDE OF THE SAME HOUSE  (2026-10-15)
   Every colour below is a token the stylesheet already reads, so the whole house turns over at once and not
   one rule had to be rewritten. The dark side keeps the values it always had; this block only says what is
   different when the visitor has pulled the cord.
   WHY THE ACCENT GETS A SECOND NAME: on the dark page the brand gold is bright and reads as text. On paper
   the same gold is almost invisible - measured, #ffd700 on #f4f1ea is about 1.3:1. So `--accent-text` is the
   only thing that changes: the BUTTON keeps the brand colour (dark ink on bright gold works on paper too),
   while anything that writes the accent AS TEXT takes the darkened one. In the dark both are the same value,
   which is why nothing moved there.
   =========================================================================================================== */

:root { --accent-text: var(--accent); }

:root[data-theme="light"] {
    --page-bg: #f4f1ea;                            /* warm paper: the dark side's warm ink, turned over */
    --section-alt: #e9e4da;
    --page-ink: #221f1a;
    --muted: #6d6558;
    --line: rgba(34, 31, 26, .16);

    --card-bg: rgba(255, 255, 255, .66);
    --card-line: rgba(34, 31, 26, .10);
    --card-shadow: 0 8px 32px rgba(34, 31, 26, .12);
    --card-edge: inset 0 1px 0 rgba(255, 255, 255, .9);
    --card-solid: #ffffff;

    --header-bg: rgba(244, 241, 234, .55);
    --header-bg-solid: rgba(244, 241, 234, .95);

    /* Darkened rather than replaced: whatever accent the office chose still decides the hue. */
    --accent-text: color-mix(in srgb, var(--accent) 42%, #000000);

    /* The tints and the glow follow the accent chosen for this site, not the bright value frozen for a
       dark page: a 12% gold wash that reads as warmth on black reads as a stain on paper. */
    --accent-soft: color-mix(in srgb, var(--accent) 15%, transparent);
    --accent-line: color-mix(in srgb, var(--accent) 38%, transparent);
    --glow: color-mix(in srgb, var(--accent) 22%, transparent);
}

/* THE THINGS THAT WERE PAINTED WHITE BY HAND. Each one was a white that only made sense on black. */
:root[data-theme="light"] .btn-ghost { border-color: rgba(34, 31, 26, .22); }
:root[data-theme="light"] .btn-ghost:hover { background: rgba(34, 31, 26, .06); }
:root[data-theme="light"] .lang-switch > summary:hover,
:root[data-theme="light"] .lang-switch[open] > summary { background: rgba(34, 31, 26, .08); }
:root[data-theme="light"] .lang-switch a[aria-current="true"] { background: rgba(34, 31, 26, .08); }
:root[data-theme="light"] .lang-menu a:hover,
:root[data-theme="light"] .lang-menu a:focus-visible { background: rgba(34, 31, 26, .06); }
:root[data-theme="light"] .nav-sub-link:hover,
:root[data-theme="light"] .nav-sub-link:focus-visible { background: rgba(34, 31, 26, .06); }
:root[data-theme="light"] .table-dark { background: rgba(255, 255, 255, .55); }
:root[data-theme="light"] table.prices tbody tr:hover { background: rgba(34, 31, 26, .03); }
:root[data-theme="light"] .note { background: rgba(255, 255, 255, .5); }
:root[data-theme="light"] input,
:root[data-theme="light"] select,
:root[data-theme="light"] textarea { background: rgba(255, 255, 255, .72); }
:root[data-theme="light"] select option { background: #ffffff; color: var(--page-ink); }
:root[data-theme="light"] input::placeholder,
:root[data-theme="light"] textarea::placeholder { color: rgba(34, 31, 26, .45); }
:root[data-theme="light"] .site-header.is-scrolled { box-shadow: 0 10px 30px rgba(34, 31, 26, .10); }
:root[data-theme="light"] .nav { box-shadow: 0 22px 46px rgba(34, 31, 26, .18); }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    :root[data-theme="light"] .card { background: rgba(255, 255, 255, .92); }
}

/* THE CROSSFADE. The whole house turns over in half a second instead of jumping, and the transition is
   carried by the page only while it happens - a transition left on every element is a page that feels
   slow for the rest of its life. */
html.theme-switching,
html.theme-switching * {
    transition: background-color .5s ease, color .5s ease, border-color .5s ease,
                box-shadow .5s ease, fill .5s ease, stroke .5s ease !important;
}

/* ===========================================================================================================
   THE SKY OF THE LIGHT SIDE  (the owner's order, 2026-10-15)
   The dark side of this house is night: near-black, warm ink, one amber lamp. The light side could have been
   nothing more than the same page inverted - and inverted pages look like a photograph held up to a window.
   It is a day instead. `Aozora`, the blue sky, sits at the top of the page and settles into warm paper by the
   time the first line of content arrives, so the colour is the mood and never the reading surface.
   The four blues are the owner's own (- #E6F2FF - #B3D9FF - #80B3FF - #6699E6 -), and the gradient is fixed so
   the sky stays where it is while the page scrolls under it, the way a real one does.
   The grain that came with the gradient (a 256px tile at 2% in `overlay`) is deliberately NOT here: at two
   per cent it is invisible, and it would have meant shipping a 20 KB base64 image inside the stylesheet that
   every visitor downloads on every page. Carrying twenty kilobytes to be seen by nobody is not a detail.
   =========================================================================================================== */

:root[data-theme="light"] body {
    background-color: var(--page-bg);
    background-image: linear-gradient(180deg,
        #E6F2FF 0%,
        #B3D9FF 22%,
        #80B3FF 40%,
        rgba(244, 241, 234, 0) 66%);
    background-repeat: no-repeat;
    background-size: 100% 100vh;
    background-attachment: fixed;
}
/* The header sits in the sky, so it must not paint the paper colour over it. */
:root[data-theme="light"] .site-header { background: rgba(230, 242, 255, .45); }
:root[data-theme="light"] .site-header.is-scrolled { background: rgba(244, 241, 234, .92); }
/* A band that alternates stays paper: two skies one under the other is not a day, it is a wallpaper. */
:root[data-theme="light"] .section-alt { background: var(--section-alt); }


/* The mark is drawn in cream because it was made for a black wall. On paper it disappears - measured, the
   cream on the sky is about 1.1:1. It is one flat colour on transparency, so inverting it turns the SAME
   file into the dark mark; no second logo had to be drawn, added, or kept in step with this one. */
:root[data-theme="light"] img[src*="logo-cream"] { filter: invert(1); }


/* ===========================================================================================================
   EVERY BAND CATCHES ITS OWN LIGHT  (the owner's order, 2026-10-15)
   "make each part have its own gradient - dark at the top, the light colour below". The page was one flat
   wall with every other band a single flat tone; now each band is darker where it begins and lighter where
   it ends, so a long page reads as stacked panels catching a light from the side instead of as wallpaper.
   The values are DERIVED, not picked: whatever ground the office chooses in the appearance settings, each
   band darkens and lightens around it, so this keeps working when the colours change.
   WHY THE LIGHT SIDE IS LEFT OUT: its depth is the sky, and the sky lives on the body. A band with a
   background of its own is opaque, so the first `.section` would have painted straight over it and the day
   would have been a strip at the top of the page. On paper the bands keep the flat tones they had.
   =========================================================================================================== */

:root:not([data-theme="light"]) .section {
    background-image: linear-gradient(180deg,
        color-mix(in srgb, var(--page-bg) 88%, #000) 0%,
        color-mix(in srgb, var(--page-bg) 88%, #fff) 100%);
}
:root:not([data-theme="light"]) .section-alt {
    background-color: var(--section-alt);
    background-image: linear-gradient(180deg,
        color-mix(in srgb, var(--section-alt) 88%, #000) 0%,
        color-mix(in srgb, var(--section-alt) 88%, #fff) 100%);
}


/* ===========================================================================================================
   THE LIGHT SWITCH  (2026-10-15 - the second version)
   A pull-cord hung here first: a rope with a bead that switched the house when it was pulled. It was taken
   away on the owner's word - *"make it just a button, take the rope away"* - after two faults of mine: the
   button that carried it was left the height of the rope and lay invisibly over the top-left of every page,
   and the rope had no end, following the hand down the page for as long as the hand kept going.
   A control understood in the first second beats a control enjoyed in the third.
   It stands first in the row of small controls, beside the language and the sign-in, and carries a sun on
   the dark side and a moon on the light one - drawn in the script, so no icon font and no extra request.
   =========================================================================================================== */

.theme-switch {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; padding: 0; margin: 0; flex: 0 0 auto;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--page-ink);
    cursor: pointer;
    transition: border-color .18s ease, color .18s ease, background-color .18s ease, transform .18s ease;
}
.theme-switch:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
    .theme-switch:hover { border-color: var(--accent); color: var(--accent-text); }
}
.theme-switch:active { transform: scale(.94); }
.theme-switch:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
.theme-switch svg { display: block; }
@media (max-width: 980px) {
    /* The folded header is tight - folding the two languages into one is what made this fit at 360px - so
       the button gives back a little of what it takes. */
    .theme-switch { width: 32px; height: 32px; }
}


/* In the folded menu the switch is a row like the links, not a bead in a tight row. It says what it is,
   because a bare sun in a list of words is a riddle. */
.theme-switch-in-menu {
    width: auto; height: auto; align-self: stretch; justify-content: flex-start; gap: 10px;
    padding: 13px 0; margin: 0; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
    font-size: 16px; color: var(--page-ink);
}
.theme-switch-in-menu::after { content: attr(data-label); font-size: 16px; }
.theme-switch-in-menu:focus-visible { color: var(--accent-text); }
@media (hover: hover) and (pointer: fine) {
    .theme-switch-in-menu:hover { border-color: transparent; border-bottom-color: var(--line); color: var(--accent-text); }
}

@media (max-width: 980px) { .theme-switch { width: 32px; height: 32px; } .theme-switch-in-menu { width: auto; height: auto; } }


/* ===========================================================================================================
   THE STREAKS OVER THE HERO ARE GONE  (the owner's order, 2026-10-15)
   *"и тргни го тоа прелазот преку нив - ако може"*. A hatch of white lines at 3.5% and a wide amber glow were
   laid over the hero as a texture. On the dark side they were barely there; on paper they read as a smear
   across the words, and they were the thing standing between the eye and "About us".
   Removed with one line instead of by editing forty pages: the element stays in the markup, so nothing has to
   be put back if this is ever wanted again.
   =========================================================================================================== */

.hero-streaks { display: none !important; }


/* ===========================================================================================================
   WHAT THE DESIGN SKILLS FOUND IN MY OWN WORK  (2026-10-15, after the owner's correction that I read the
   skills and do not apply them - which was true)
   From `emil-design-eng`, applied to what I wrote earlier in this session:
     1. Hover styles stood without a media query. A touch device fires `:hover` on tap, so a style that only
        makes sense under a mouse becomes a false positive under a finger. Gated - `:focus-visible` left out
        of the gate, because a keyboard on a tablet still needs it.
     2. The two drop-downs FADED in from nothing and used the weak built-in `ease`. "Nothing in the real world
        disappears and reappears completely", and a popover should be seen to come from its trigger, not from
        the middle of the screen. They now rise four pixels and grow from 0.97 - never from 0 - anchored at
        the trigger with `transform-origin`, on the stronger `cubic-bezier(0.23, 1, 0.32, 1)` curve.
   NOT changed, and why: the half-second crossfade when the house turns over. `emil-design-eng` asks for under
   300ms, but `design-motion-principles` says NOT to cap durations universally and to weight the context
   first - and this is a marketing page, where the weighting is Jakub's 200-500ms. 500ms is in range. The
   second skill stopped me from "fixing" something that was right.
   =========================================================================================================== */

.nav-item .nav-sub {
    transform-origin: top center;
    transform: translateX(-50%) translateY(-5px) scale(.97);
    transition: opacity .16s cubic-bezier(.23, 1, .32, 1),
                visibility .16s cubic-bezier(.23, 1, .32, 1),
                transform .16s cubic-bezier(.23, 1, .32, 1);
}
.nav-item:hover .nav-sub,
.nav-item:focus-within .nav-sub { transform: translateX(-50%) translateY(0) scale(1); }

.lang-menu {
    transform-origin: top right;
    transform: translateY(-5px) scale(.97);
    transition: opacity .16s cubic-bezier(.23, 1, .32, 1), transform .16s cubic-bezier(.23, 1, .32, 1);
}
.lang-switch[open] .lang-menu { transform: translateY(0) scale(1); }
.lang-menu { opacity: 0; visibility: hidden; }
.lang-switch[open] .lang-menu { opacity: 1; visibility: visible; }
