/* ---------------------------------------------------------------------------
 * DTS — component styles
 *
 * Hand-written. Only for things Tailwind utilities can't express inline:
 * pseudo-elements, transitions, aspect-ratio placeholders, carousel state.
 * Every colour comes from brand.css custom properties — never a raw hex.
 * ------------------------------------------------------------------------- */

/* ============================== HEADER ================================== */
/* Heights live here (not in utilities) so the scrolled state can animate
   between them without fighting responsive class precedence. */
/* Single white bar — the black utility strip is gone. The logo is deliberately
   oversized relative to the bar so it reads big.
   NOTE: our mark is 1.374:1 (near square) where the reference nav logo is
   2.53:1, so matching its *width* takes far more height than it does there.
   The bar is a fixed height at every scroll position — no condense-on-scroll. */
.site-bar  { height: 88px; }
.site-logo { height: 74px; width: auto; }

@media (min-width: 1024px) {
    .site-bar  { height: 128px; }
    .site-logo { height: 116px; }   /* ~159px wide */
}
@media (min-width: 1280px) {
    .site-bar  { height: 124px; }
    .site-logo { height: 112px; }
}

/* Mobile menu: animates open by transitioning grid rows 0fr -> 1fr, which
   eases to the menu's natural height without hard-coding one. Visibility
   flips after the close finishes, so closed links can't be tabbed to. */
.mobile-menu {
    display: grid;
    grid-template-rows: 0fr;
    visibility: hidden;
    transition: grid-template-rows .4s cubic-bezier(.22, .61, .36, 1),
                box-shadow .4s ease,
                visibility 0s linear .4s;
}
.mobile-menu.is-open {
    grid-template-rows: 1fr;
    visibility: visible;
    box-shadow: 0 10px 15px -3px color-mix(in srgb, var(--ink) 10%, transparent),
                0 4px 6px -4px color-mix(in srgb, var(--ink) 10%, transparent);
    transition: grid-template-rows .4s cubic-bezier(.22, .61, .36, 1),
                box-shadow .4s ease,
                visibility 0s;
}
.mobile-menu__clip { min-height: 0; overflow: hidden; }
.mobile-menu__nav {
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity .25s ease, transform .3s ease;
}
.mobile-menu.is-open .mobile-menu__nav {
    opacity: 1;
    transform: none;
    transition-delay: .08s;
}
/* The active-page rule is a desktop-nav device. Stacked, it floats in the gap
   below the link and reads as a stray line, so the mobile menu marks the
   current page with the blue link colour alone. */
.mobile-menu .nav-link::after { content: none; }

@media (min-width: 1024px) { .mobile-menu { display: none; } }
@media (prefers-reduced-motion: reduce) {
    .mobile-menu, .mobile-menu.is-open,
    .mobile-menu__nav, .mobile-menu.is-open .mobile-menu__nav { transition: none; }
}

/* Nav links: graphite by default, fleet blue on hover/active, with an orange
   rule under the current page. */
.nav-link {
    position: relative;
    color: var(--ink);
    transition: color .15s ease;
}
.nav-link:hover,
.nav-link:focus-visible { color: var(--fleet-blue); }

.nav-link::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -6px;
    height: 3px;
    background: var(--signal-orange);
    transform: scaleX(0);
    transition: transform .18s ease;
}
.nav-link:hover::after      { transform: scaleX(.4); }
.nav-link.is-active         { color: var(--fleet-blue); }
.nav-link.is-active::after  { transform: scaleX(1); }

/* Utility bar + footer sit on dark grounds, where fleet blue only reaches
   2.93-3.15:1. Links there are light, and go orange on hover (4.60-4.93:1). */
.on-dark-link {
    color: var(--fleet-blue-12);
    transition: color .15s ease;
}
.on-dark-link:hover,
.on-dark-link:focus-visible { color: var(--signal-orange); }

/* ---------------------------- PAGE BANNERS -----------------------------
   Services, Our Work and About share one banner band. Height is set here,
   not left to the headline, so the three pages match instead of drifting
   with the length of their copy. Artwork is supplied at 1920 x 800 and is
   cropped to this band, so keep the subject away from the edges. */
.page-banner {
    display: flex;
    align-items: center;
    min-height: 420px;
}
@media (min-width: 1024px) { .page-banner { min-height: 440px; } }
/* Very narrow phones wrap the headlines onto an extra line, so the band needs
   a little more room to stay level across the three pages. */
@media (max-width: 380px)  { .page-banner { min-height: 460px; } }

/* ============================ IMAGE PLACEHOLDER ========================= */
/* Grey box carrying its intended size + subject. Replaced by real photography
   as the client supplies it. */
.img-ph {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    width: 100%;
    padding: 1.5rem 1rem;
    text-align: center;
    background: color-mix(in srgb, var(--ink) 8%, var(--signal-orange-12));
    border: 1px dashed color-mix(in srgb, var(--ink) 25%, transparent);
    color: color-mix(in srgb, var(--ink) 65%, transparent);
}
.img-ph__size {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .08em;
    color: color-mix(in srgb, var(--ink) 80%, transparent);
}
.img-ph__note {
    max-width: 34ch;
    font-size: .8125rem;
    line-height: 1.4;
    text-transform: uppercase;
    letter-spacing: .06em;
}
.img-ph--dark {
    background: color-mix(in srgb, var(--fleet-blue-12) 12%, var(--ink));
    border-color: color-mix(in srgb, var(--fleet-blue-12) 30%, transparent);
    color: color-mix(in srgb, var(--fleet-blue-12) 75%, transparent);
}
.img-ph--dark .img-ph__size { color: var(--fleet-blue-12); }

/* ============================== CAROUSEL ================================ */
.hero-slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity .7s ease-in-out;
}
.hero-slide.is-active {
    opacity: 1;
    pointer-events: auto;
}
.hero-dot {
    height: 4px;
    width: 32px;
    background: color-mix(in srgb, var(--fleet-blue-12) 40%, transparent);
    transition: background .3s ease, width .3s ease;
}
.hero-dot.is-active {
    background: var(--signal-orange);
    width: 48px;
}

/* ============================== GALLERY ================================= */
/* CSS columns give a masonry feel without a layout library, and hiding a
   tile during filtering simply reflows the columns. */
.gallery-grid { column-gap: 1.25rem; }
.gallery-grid > * { break-inside: avoid; margin-bottom: 1.25rem; }

@media (min-width: 640px)  { .gallery-grid { column-count: 2; } }
@media (min-width: 1024px) { .gallery-grid { column-count: 3; } }

.filter-chip {
    border: 1px solid color-mix(in srgb, var(--ink) 20%, transparent);
    color: var(--ink);
    background: transparent;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.filter-chip:hover { border-color: var(--signal-orange); }
.filter-chip.is-active {
    background: var(--signal-orange);
    border-color: var(--signal-orange);
    color: var(--ink);   /* 4.93:1 on orange — white would fail */
}


/* ============================== TEXTURES ================================
 * Generated inline SVG — no stock assets, no CDN, a few hundred bytes each,
 * and tintable via currentColor-ish fills. Always applied as a ::before
 * overlay so they never sit between the reader and the text.
 * `--tex-shift` is nudged by site.js on scroll for a parallax drift.
 * ===================================================================== */
.tex { position: relative; isolation: isolate; overflow: hidden; }
.tex > * { position: relative; z-index: 1; }
.tex::before {
    content: "";
    position: absolute;
    inset: -20% 0 -20% 0;
    z-index: 0;
    pointer-events: none;
    background-repeat: no-repeat;
    transform: translate3d(0, var(--tex-shift, 0px), 0);
    will-change: transform;
}

/* Circular swirls — ONE composition, drawn at 1600x900 and scaled to cover.
   Deliberately never repeats: a tiled pattern showed visible seams where the
   strokes failed to meet at the tile edges. Kept very faint. */
.tex-swirl::before,
.tex-glow::before {
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
}

.tex-swirl::before {
    opacity: .85;
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201600%20900'%20preserveAspectRatio='xMidYMid%20slice'%3E%3Cg%20fill='none'%20stroke='%23101828'%20stroke-opacity='.05'%20stroke-width='2.5'%3E%3Ccircle%20cx='250'%20cy='240'%20r='120'/%3E%3Ccircle%20cx='250'%20cy='240'%20r='190'/%3E%3Ccircle%20cx='250'%20cy='240'%20r='265'/%3E%3Ccircle%20cx='250'%20cy='240'%20r='345'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23101828'%20stroke-opacity='.035'%20stroke-width='2.5'%3E%3Ccircle%20cx='1290'%20cy='700'%20r='150'/%3E%3Ccircle%20cx='1290'%20cy='700'%20r='230'/%3E%3Ccircle%20cx='1290'%20cy='700'%20r='320'/%3E%3Ccircle%20cx='1290'%20cy='700'%20r='415'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23101828'%20stroke-opacity='.045'%20stroke-width='2.5'%3E%3Ccircle%20cx='820'%20cy='180'%20r='90'/%3E%3Ccircle%20cx='820'%20cy='180'%20r='165'/%3E%3Ccircle%20cx='820'%20cy='180'%20r='250'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23101828'%20stroke-opacity='.03'%20stroke-width='2.5'%3E%3Ccircle%20cx='640'%20cy='820'%20r='110'/%3E%3Ccircle%20cx='640'%20cy='820'%20r='185'/%3E%3Ccircle%20cx='640'%20cy='820'%20r='270'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23101828'%20stroke-opacity='.05'%20stroke-width='3'%20stroke-linecap='round'%3E%3Cpath%20d='M-100%20620C220%20380%20520%20760%20860%20520S1380%20200%201720%20420'/%3E%3Cpath%20d='M-100%20300C260%20120%20540%20420%20900%20260S1420%2040%201720%20180'/%3E%3Cpath%20d='M-100%20880C300%20700%20620%20940%20980%20800S1500%20620%201720%20720'/%3E%3C/g%3E%3C/svg%3E");
}

/* the same swirls in white, for ink / blue / purple grounds */
.tex-swirl--dark::before {
    opacity: .8;
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201600%20900'%20preserveAspectRatio='xMidYMid%20slice'%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.07'%20stroke-width='2.5'%3E%3Ccircle%20cx='250'%20cy='240'%20r='120'/%3E%3Ccircle%20cx='250'%20cy='240'%20r='190'/%3E%3Ccircle%20cx='250'%20cy='240'%20r='265'/%3E%3Ccircle%20cx='250'%20cy='240'%20r='345'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.05'%20stroke-width='2.5'%3E%3Ccircle%20cx='1290'%20cy='700'%20r='150'/%3E%3Ccircle%20cx='1290'%20cy='700'%20r='230'/%3E%3Ccircle%20cx='1290'%20cy='700'%20r='320'/%3E%3Ccircle%20cx='1290'%20cy='700'%20r='415'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.06'%20stroke-width='2.5'%3E%3Ccircle%20cx='820'%20cy='180'%20r='90'/%3E%3Ccircle%20cx='820'%20cy='180'%20r='165'/%3E%3Ccircle%20cx='820'%20cy='180'%20r='250'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.045'%20stroke-width='2.5'%3E%3Ccircle%20cx='640'%20cy='820'%20r='110'/%3E%3Ccircle%20cx='640'%20cy='820'%20r='185'/%3E%3Ccircle%20cx='640'%20cy='820'%20r='270'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.07'%20stroke-width='3'%20stroke-linecap='round'%3E%3Cpath%20d='M-100%20620C220%20380%20520%20760%20860%20520S1380%20200%201720%20420'/%3E%3Cpath%20d='M-100%20300C260%20120%20540%20420%20900%20260S1420%2040%201720%20180'/%3E%3Cpath%20d='M-100%20880C300%20700%20620%20940%20980%20800S1500%20620%201720%20720'/%3E%3C/g%3E%3C/svg%3E");
}

/* saturated colour bands: swirls over a soft tonal wash */
.tex-glow::before {
    opacity: .9;
    background-image:
        url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201600%20900'%20preserveAspectRatio='xMidYMid%20slice'%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.07'%20stroke-width='2.5'%3E%3Ccircle%20cx='250'%20cy='240'%20r='120'/%3E%3Ccircle%20cx='250'%20cy='240'%20r='190'/%3E%3Ccircle%20cx='250'%20cy='240'%20r='265'/%3E%3Ccircle%20cx='250'%20cy='240'%20r='345'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.05'%20stroke-width='2.5'%3E%3Ccircle%20cx='1290'%20cy='700'%20r='150'/%3E%3Ccircle%20cx='1290'%20cy='700'%20r='230'/%3E%3Ccircle%20cx='1290'%20cy='700'%20r='320'/%3E%3Ccircle%20cx='1290'%20cy='700'%20r='415'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.06'%20stroke-width='2.5'%3E%3Ccircle%20cx='820'%20cy='180'%20r='90'/%3E%3Ccircle%20cx='820'%20cy='180'%20r='165'/%3E%3Ccircle%20cx='820'%20cy='180'%20r='250'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.045'%20stroke-width='2.5'%3E%3Ccircle%20cx='640'%20cy='820'%20r='110'/%3E%3Ccircle%20cx='640'%20cy='820'%20r='185'/%3E%3Ccircle%20cx='640'%20cy='820'%20r='270'/%3E%3C/g%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='.07'%20stroke-width='3'%20stroke-linecap='round'%3E%3Cpath%20d='M-100%20620C220%20380%20520%20760%20860%20520S1380%20200%201720%20420'/%3E%3Cpath%20d='M-100%20300C260%20120%20540%20420%20900%20260S1420%2040%201720%20180'/%3E%3Cpath%20d='M-100%20880C300%20700%20620%20940%20980%20800S1500%20620%201720%20720'/%3E%3C/g%3E%3C/svg%3E"),
        radial-gradient(70% 90% at 20% 25%, rgba(255,255,255,.10), transparent 64%),
        radial-gradient(65% 85% at 82% 80%, rgba(0,0,0,.14), transparent 66%);
    background-size: cover, cover, cover;
    background-repeat: no-repeat, no-repeat, no-repeat;
}

/* ============================ CARTOON / LINE-ART BITS ====================== */
/* Outlined circle holding a line icon — the reference "STEP 01" treatment. */
.line-circle {
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    border: 3px solid currentColor;
    aspect-ratio: 1;
}
/* Outlined numeral, like the reference's hollow "01" */
.numeral-outline {
    color: transparent;
    -webkit-text-stroke: 2px currentColor;
    paint-order: stroke fill;
}

/* Curved arrow connecting steps (hidden when the row stacks) */
.step-arrow { color: color-mix(in srgb, var(--signal-orange) 65%, transparent); }

/* ============================ PHOTO TILES ============================= */
/* Reference pattern: full-bleed photo, white label bar at lower-left, solid
   arrow button on its right edge. */
.tile { position: relative; display: block; overflow: hidden; }
.tile__label {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    display: flex;
    align-items: stretch;
    margin: 0 1rem 1rem 1rem;
}
.tile__name {
    flex: 1;
    background: #fff;
    color: var(--ink);
    padding: .75rem 1rem;
    font-size: 1.0625rem;
    font-weight: 600;
    line-height: 1.2;
}
.tile__go {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    background: var(--signal-orange);
    color: var(--ink);
    transition: transform .15s ease, background-color .2s ease, color .2s ease;
}
.tile:hover .tile__go {
    transform: translate(2px, -2px);
    background: var(--vinyl-purple);
    color: #fff;              /* graphite on purple is 2.34:1 — must go white */
}
.tile:hover .tile__name { color: var(--fleet-blue); }

/* =========================== ANCHOR TARGETS ============================= */
/* The header is sticky (~104px incl. utility bar, ~88px scrolled), so deep
   links like services.html#window-tinting must not land under it. */
[id] { scroll-margin-top: 7rem; }
@media (min-width: 1024px) { [id] { scroll-margin-top: 9rem; } }

html { scroll-behavior: smooth; }

/* ============================== MOTION ================================== */
@media (prefers-reduced-motion: reduce) {
    .nav-link, .nav-link::after,
    .hero-slide, .hero-dot, .on-dark-link { transition: none; }
    html { scroll-behavior: auto; }
    .tex::before { transform: none !important; }
    .tile__go { transition: none; }
}
