@charset "UTF-8";
/* ==========================================================================
   JSENSE "MAISON" LUXURY DESIGN SYSTEM v5 - "Atelier Taupe"
   Fraunces - Jost - Noto Serif TC/SC
   2026-09-07: re-themed from "Atelier" (dark espresso/brass/wine) to a light taupe/cream
   direction, matched directly to the J.SENSE printed business card (same reference photo and
   same --ecard-* palette used for views/front/ecard.php - see that file for the source of
   these exact hex values, confirmed against the real card). User's explicit ask: "use this
   color tones in the attached image for everything in this project" + fix two Home-page
   components (hero, Featured Collections cards) that put text directly over a photo.
   Variable NAMES kept identical to every prior pass (same precedent each time) so nothing
   referencing var(--gold)/var(--text-main)/etc. breaks - only VALUES changed here, plus 4 new
   tokens (--taupe/--taupe-deep/--cream/--coral) added for the redesigned components below.
   --gold is untouched - still reads the real admin-configurable brand gold (Settings ->
   Colors); this direction is a light surround around that existing accent, not a replacement.
   Contrast checked, not just eyeballed: --text-main on --bg ~12:1, --text-muted on --bg ~5.9:1,
   --cream on --taupe-deep ~4.5:1 (WCAG AA) - --taupe itself (the lighter mid-tone from the
   card) is intentionally NOT used as a text background for body copy, only as a decorative/
   image-adjacent surface, since cream-on-taupe alone measures only ~2.3:1.
   IMPORTANT - known limitation, not yet addressed: this file governs custom .sense- and .luxury-
   prefixed classes. Bootstrap's own dark-mode utility classes applied directly in markup
   (table-dark, bg-dark, border-secondary, text-white) are Bootstrap's own CSS, not this file's -
   their rendering depends on frontend_v80_patch.css's variable rebind, not this file directly.
   Scope of this pass: Home page (hero + Featured Collections cards, restructured) and the
   shared token system (nav/footer/every page already built on these tokens picks the new
   palette up for free, same mechanism as every prior re-theme). Gallery/Portfolio-Detail/
   Product-Detail/etc.'s own inline <style> blocks were NOT swept this pass - flagged here
   rather than silently claimed finished, matching this project's own established practice for
   every previous theme-direction change.
   ========================================================================== */

:root {
    /* -- Palette --
       2026-09-05: v2's dark near-black tones (--noir/--onyx/--charcoal/--smoke) are kept
       as-is and UNCHANGED - they're still used as literal dark values in a few places that
       need a dark tone regardless of overall theme (e.g. dark text on a gold button). */
    --noir:          #1B1815;
    --onyx:          #221D18;
    --charcoal:      #2A241D;
    --smoke:         #352C22;
    /* Surface tokens.
       Admin-configurable the same way --gold reads --primary-color below - Admin -> Settings ->
       Appearance's "Body Background Color"/"Card Background Color" pickers write --body-bg/
       --card-bg (SettingsHelper::generateColorSchemeCSS(), injected in views/layouts/header.php).
       These values are the fallback; the live Settings values were updated to match as part of
       this rollout so the two don't disagree (same precedent as every prior direction change). */
    --bg:            var(--body-bg, #f0e6d2);
    --surface:       var(--card-bg, #faf5ea);
    --line:          #e0d0b0;
    /* --gold still derives from --primary-color (Admin -> Settings -> Colors) - stays
       admin-configurable exactly as before, untouched by this direction change. */
    --gold:          var(--primary-color, #DDAB4E);
    --gold-light:    color-mix(in srgb, var(--gold) 80%, white);
    --gold-dim:      color-mix(in srgb, var(--gold) 20%, transparent);
    /* 2026-09-07, round 2 (5th pass): three straight hue tweaks (warmer -> olive -> "chocolate
       milk") each got "that's not it" feedback, ending in "the color scheme has gone off a lot,
       bring it back" with the original card photo shown again. Stopped guessing at variations
       and switched to the EXACT hex values from views/front/ecard.php's --ecard-* palette -
       that page was built directly against this same card early on and has never once drawn a
       color complaint since, so it's the one proven-correct source rather than another
       iteration of this file's own judgment. --taupe and --taupe-deep are now the same value
       (the card itself has one taupe, not two) - what used to be a legibility-driven "deep"
       variant is gone; the card's own accepted contrast is trusted as-is rather than
       re-engineered again. */
    --wine:          #b5583f;
    --taupe:         #a39a8c;
    --taupe-deep:    #a39a8c;
    --cream:         #eee7d8;
    --coral:         #dc9683;
    /* --ivory is the "brighter/emphasized" text role (nav-link hover, dropdown items, footer
       brand) - on the dark Atelier ground that was a brighter warm ivory than --text-main; on
       this light ground the same "more emphasis" relationship is preserved by going the other
       direction, darker than --text-main rather than lighter. */
    --ivory:         #332f20;
    --mist:          rgba(51,47,32,0.68);
    --text-main:     #332f20;
    --text-muted:    #605c48;
    --stroke:        #e0d0b0;
    --stroke-gold:   rgba(201,160,95,0.4);

    /* -- Typography -- */
    --font-display:  'Fraunces', 'Noto Serif TC', Georgia, serif;
    --font-ui:       'Jost', 'Segoe UI', system-ui, sans-serif;
    --font-tw:       'Noto Serif TC', 'Fraunces', serif;
    --font-cn:       'Noto Serif SC', 'Fraunces', serif;

    /* -- Font-size design tokens (overridable via Admin -> Settings -> Typography) --
       2026-09-03: bumped up a step - was legible but small throughout (nav/footer/button
       all under 14px). */
    /* 2026-09-03: fixed rem sizes kept swinging between "too small" and "too big" depending
       on the viewer's window/screen width - switched to fluid clamp() so it scales smoothly
       with viewport width instead of being one fixed number: 0.85rem (13.6px) on narrow
       windows up to 1.05rem (16.8px) on wide ones, interpolated in between via vw. */
    /* 2026-09-03: still wrapping ("ABOUT US" onto 2 lines) at the previous clamp's own max
       (0.85-1.05rem) once the admin toolbar (EN/TC/SC + ADMIN button + icons) eats into the
       navbar's available width - cut the max further and, more importantly, tightened
       .nav-link's letter-spacing below (0.20em was adding real width per nav item on top of
       the font-size itself). */
    --font-size-nav:        clamp(0.78rem, 0.72rem + 0.22vw, 0.92rem);
    --font-size-body:       1.05rem;
    --font-size-heading:    2.5rem;
    --font-size-subheading: 1.5rem;
    --font-size-card:       0.96rem;
    --font-size-footer:     0.92rem;
    --font-size-button:     0.9rem;

    /* -- Easing -- */
    --ease-luxury:   cubic-bezier(0.25, 0.46, 0.45, 0.94);
    --ease-spring:   cubic-bezier(0.34, 1.56, 0.64, 1);

    /* -- Spacing --
       2026-09-05: Showroom Light's flat, hairline-rule aesthetic replaces the previous rounded
       "luxury card" look - the pill-shaped buttons (.btn-luxury etc.) use a literal 100px
       border-radius of their own, not this token, so they're unaffected by this change. */
    /* 2026-09-07 round 2 (4th pass): 68px matches the navbar's real rendered height now that
       it's auto-sized to its actual content (46px toggle button + 10px top/bottom padding) -
       used both for body's own padding-top (clearing the fixed bar) and scroll-padding-top
       (anchor jumps land below the bar, not partly behind it). */
    --nav-h:         68px;
    --radius-sm:     2px;
    --radius:        2px;
    --radius-lg:     4px;
}

/* -- Foundation --
   2026-09-07, round 2: scroll-padding-top accounts for the fixed navbar so an anchor/in-page
   jump lands below it instead of partly behind it.
   CONFIRMED REGRESSION, fixed same day: this block briefly also added
   `overscroll-behavior-y: none` and `-webkit-overflow-scrolling: touch` to body, intended to
   make scrolling "smoother" - instead it broke wheel/trackpad scrolling almost entirely
   (reported as "only works with the scrollbar," reproduced live: window.scrollTo() and the
   native scrollbar both worked, every wheel-gesture scroll did nothing until
   overscroll-behavior-y was removed). documentElement was the real scrolling element the whole
   time (document.scrollingElement === HTML, confirmed live) - overscroll-behavior-y:none on
   BODY, which isn't the scrolling box, was enough to make this engine swallow wheel events
   meant for its ancestor. Removed outright rather than searching for a "safer" variant of the
   same property - it was solving a minor cosmetic concern (bounce past the page edge) by
   breaking the core interaction. */
html {
    scroll-behavior: smooth;
    scroll-padding-top: var(--nav-h);
}

body {
    background-color: var(--bg);
    /* 2026-09-07 round 2 (5th pass): "remove the home background patterns" - the fine noise
       grain SVG (3.5% opacity fractalNoise) removed too, along with the diagonal hairline
       texture in frontend_signature.css's .sense-section - the reference card is flat solid
       taupe/cream with no texture at all, and this round's feedback is explicitly about
       getting closer to that, not further from it. */
    color: var(--text-main);
    font-family: var(--font-ui);
    font-size: var(--font-size-body);
    font-weight: 300;
    line-height: 1.8;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    padding-top: var(--nav-h);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

/* Language body overrides */
html[lang="zh_tw"] body, html[lang="tw"] body { font-family: var(--font-tw); }
html[lang="zh_cn"] body, html[lang="cn"] body { font-family: var(--font-cn); }

/* Protect icon fonts from CJK body font override */
i.fas, i.far, i.fab, i.fal, i.fad, i.fa-solid, i.fa-regular, i.fa-brands,
.fas, .far, .fab, .fal, .fad,
[class*="fa-"] { font-family: "Font Awesome 6 Free", "Font Awesome 6 Brands", "Font Awesome 5 Free", "Font Awesome 5 Brands" !important; }

/* 2026-09-05: image-save protection, moved from a JS querySelectorAll('img') pass in
   footer.php (which only ever ran once, at DOMContentLoaded) into a plain CSS rule instead -
   a lazy-loaded gallery/product thumbnail, or the swapped #zoomImg/#mainImg in
   detail.php/product_detail.php's viewers, never existed yet when that JS pass ran, so it never
   got hardened. CSS applies to every <img> regardless of when it's inserted. Doesn't touch
   admin (this file isn't loaded there). This narrows one real gap (images added after page
   load); it does not and cannot stop Firefox's Shift+right-click bypass or a browser's own
   Network tab / view-source - no client-side rule can. */
img {
    -webkit-user-drag: none;
    -khtml-user-drag: none;
    user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
}

/* Container */
.container, .container-fluid { padding-left: 2vw !important; padding-right: 2vw !important; }
.navbar .container-xxl, .navbar .container-fluid { padding-left: 1.25rem !important; padding-right: 1.25rem !important; }

/* -- Typography -- */
h1, h2, h3, h4, .luxury-title, .luxury-page-title, .hero-title {
    font-family: var(--font-display);
    font-weight: 400;
    /* 2026-09-05: was a hardcoded #fff (white-on-dark) - the one hardcoded, non-token color in
       this whole file's typography, would have rendered invisible white-on-cream otherwise. */
    color: var(--text-main);
    letter-spacing: 0.04em;
    line-height: 1.15;
}
h1 { font-size: clamp(2rem, 5vw, 4rem); margin-bottom: 1.5rem; }
h2 { font-size: clamp(1.6rem, 3vw, 2.8rem); margin-bottom: 1.2rem; }
h3 { font-size: clamp(1.2rem, 2vw, 1.8rem); margin-bottom: 1rem; }
p.lead { font-size: 1.05rem; color: var(--mist); line-height: 1.9; }

html[lang="zh_tw"] h1, html[lang="zh_tw"] h2, html[lang="zh_tw"] h3,
html[lang="zh_cn"] h1, html[lang="zh_cn"] h2, html[lang="zh_cn"] h3 {
    font-family: var(--font-tw);
    letter-spacing: 0.06em;
}

/* Utility */
.text-gold  { color: var(--gold) !important; }
.text-ivory { color: var(--ivory) !important; }
.text-muted { color: var(--text-muted) !important; }

/* Decorative gold divider line */
.gold-rule {
    display: block;
    width: 60px; height: 1px;
    background: linear-gradient(90deg, transparent, var(--gold), transparent);
    margin: 1rem auto;
}
/* Ornamental section heading kicker */
.kicker {
    display: inline-flex; align-items: center; gap: 10px;
    font-family: var(--font-ui);
    font-size: 0.68rem; letter-spacing: 0.3em; text-transform: uppercase;
    color: var(--gold);
}
.kicker::before, .kicker::after {
    content: ''; flex: 1; height: 1px;
    background: linear-gradient(90deg, transparent, var(--gold) 60%);
    display: inline-block; min-width: 30px;
}
.kicker::after { background: linear-gradient(270deg, transparent, var(--gold) 60%); }

/* -- Navbar --
   2026-09-07 round 2 (3rd pass): "remove the color strip on top" + "menu background color be
   same as the main page background color" - the navbar no longer reads as a distinct dark bar
   at all; it's var(--bg), the same token the page body uses, and the ::before gold gradient
   line is gone. A hairline border (var(--stroke)) is enough to separate it from content
   scrolling underneath. */
.navbar-glass {
    position: fixed; top: 0; left: 0; right: 0;
    z-index: 2500;
    /* 2026-09-07 round 2 (4th pass): was a fixed height:var(--nav-h) - the logo (now moved out
       of the top bar entirely, see header.php) used to force this to overflow:visible since it
       was taller than any fixed height could account for. Auto height + min-height instead, so
       the bar just fits its real content (header.php's own inline override sets the actual
       padding). */
    height: auto;
    min-height: var(--nav-h);
    background: var(--bg) !important;
    border-bottom: 1px solid var(--stroke) !important;
    box-shadow: none !important;
    transition: background 0.5s var(--ease-luxury), box-shadow 0.5s var(--ease-luxury);
}
.navbar-glass.scrolled {
    /* Overridden again (same properties) by header.php's own inline <style> block, which loads
       later and wins the tie - kept in sync here too rather than left as a stale literal that
       would resurface if that inline override is ever removed. */
    background: var(--bg) !important;
    border-bottom: 1px solid var(--stroke-gold) !important;
    box-shadow: 0 4px 20px rgba(38,30,20,0.1) !important;
}

/* 2026-09-03: removed the base .brand-text{...} rule that used to be here - every one of its
   properties was shadowed by views/layouts/header.php's own .brand-text rule (later in the
   cascade, equal-or-higher !important), so it never actually rendered; header.php's rule now
   explicitly carries font-weight:600 (the one property that WAS coming from here) so the
   visual result is unchanged. :hover stays here since header.php has no equivalent - this is
   genuinely the only source for it. */
.brand-text:hover { letter-spacing: 0.35em !important; color: var(--gold-light) !important; }

.nav-link {
    font-family: var(--font-ui);
    font-size: var(--font-size-nav) !important;
    font-weight: 500;
    letter-spacing: 0.10em; /* 2026-09-03: was 0.20em - wide tracking was adding real width per
        item ("ABOUT US" specifically was wrapping to 2 lines because of font-size + spacing
        combined, not font-size alone) */
    /* 2026-09-07: was var(--text-muted) (dark) - correct for page content on the new light
       background, wrong here: the navbar itself is a fixed translucent --taupe-deep panel
       (see .navbar-glass), so nav text needs light/cream, same reasoning as every other
       dark-panel component this pass touched. Not using --text-muted/--ivory here since those
       are now page-level DARK tokens for the light body background - the navbar is a
       permanently dark-ish surface regardless of the overall page theme, so it gets its own
       explicit cream-based values instead of sharing tokens with page content. */
    color: rgba(238,231,216,0.8) !important;
    text-transform: uppercase;
    padding: 6px 10px !important;
    position: relative;
    transition: color 0.3s ease;
}
/* Underline */
.nav-link::after {
    content: '';
    position: absolute; bottom: 2px; left: 50%;
    width: 0; height: 1px;
    background: linear-gradient(90deg, transparent, var(--gold), transparent);
    transition: width 0.4s var(--ease-luxury), left 0.4s var(--ease-luxury);
}
.nav-link:hover::after, .nav-link.active::after { width: 70%; left: 15%; }
.nav-link:hover, .nav-link.active { color: var(--cream, #eee7d8) !important; }

html[lang="zh_tw"] .nav-link,
html[lang="zh_cn"] .nav-link { font-family: var(--font-tw) !important; font-size: clamp(0.86rem, 0.78rem + 0.2vw, 1rem) !important; letter-spacing: 0.06em; }
/* 2026-09-03: cut down alongside the English clamp/letter-spacing above (same overflow/
   wrapping issue at the previous, larger values) - kept modestly larger than English per the
   usual CJK-density adjustment, just less so than before. */

/* 2026-09-03: removed the .dropdown-menu{...} block that used to be here - its border/
   border-top (the only two properties that were actually winning, via !important) are now in
   views/layouts/header.php's own consolidated .dropdown-menu rule (which also absorbed a
   second competing block that used to live further down that same file - see its comment).
   Every other property here (background/backdrop-filter/padding/box-shadow/min-width) was
   already losing to header.php's rule even before this cleanup, so removing them changes
   nothing.
   NOT removed: .dropdown-item and .icon-link directly below, despite also having competing
   rules in header.php - unlike .dropdown-menu, they're a genuine partial MERGE, not simple
   duplication. header.php's .dropdown-item wins font-size/padding/color/transition, but this
   file's text-transform:uppercase and part of the ::before pseudo-element's background-color
   (set implicitly via this rule's `background: var(--gold)` shorthand, which header.php's
   longhand background-image never touches) are still the only source and DO still render.
   .icon-link similarly still needs this file's display:inline-flex/align-items/justify-content
   - header.php doesn't set those. A real cleanup here needs a careful property-by-property
   pass per rule (like the one just done for .dropdown-menu/.brand-text/.nav-link above), not a
   bulk delete - left alone rather than risk a visual regression under time pressure. */
.dropdown-item {
    font-family: var(--font-ui);
    font-size: 0.78rem;
    font-weight: 400;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-main);
    padding: 11px 20px 11px 32px !important;
    position: relative;
    border-bottom: 1px solid rgba(27,26,23,0.06);
    transition: all 0.22s var(--ease-luxury);
}
.dropdown-item::before {
    content: ''; position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
    width: 8px; height: 1px;
    background: var(--gold); opacity: 0;
    transition: opacity 0.22s ease, width 0.22s ease;
}
.dropdown-item:hover::before { opacity: 1; width: 12px; }
.dropdown-item:hover {
    background: var(--gold-dim);
    color: var(--gold-light) !important;
    padding-left: 38px !important;
}
.dropdown-item:last-child { border-bottom: none; }

html[lang="zh_tw"] .dropdown-item,
html[lang="zh_cn"] .dropdown-item { font-family: var(--font-tw) !important; font-size: 0.92rem !important; }

/* Navbar right controls */
.icon-link {
    color: var(--text-muted);
    font-size: 1.05rem;
    text-decoration: none;
    transition: color 0.3s ease, transform 0.3s var(--ease-spring);
    display: inline-flex; align-items: center; justify-content: center;
}
.icon-link:hover { color: var(--gold); transform: translateY(-2px); }

/* Language select */
.lang-select select {
    background: rgba(27,26,23,0.04) !important;
    color: var(--text-main) !important;
    border: 1px solid var(--line) !important;
    border-radius: 100px !important;
    padding: 3px 28px 3px 12px !important;
    font-family: var(--font-ui);
    font-size: 0.68rem;
    letter-spacing: 0.12em;
    cursor: pointer;
    outline: none;
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%2393713f'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: calc(100% - 10px) center !important;
    transition: border-color 0.3s ease, background-color 0.3s ease;
}
.lang-select select:focus { border-color: var(--gold) !important; box-shadow: 0 0 0 2px rgba(147,113,63,0.15) !important; }
.lang-select select option { background: #fff !important; color: var(--text-main) !important; }

/* -- Buttons -- */
.btn {
    font-family: var(--font-ui);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    transition: all 0.35s var(--ease-luxury);
}
.btn-luxury {
    background: linear-gradient(135deg, var(--gold) 0%, var(--gold-light) 100%);
    color: var(--noir) !important;
    border: none;
    border-radius: 100px;
    padding: 0.75rem 2rem;
    /* 2026-09-05: Showroom Light restrains gold to a "precision accent" rather than a glow -
       dropped the heavy box-shadow bloom that suited the old dark backdrop. */
    box-shadow: none;
}
.btn-luxury:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(147,113,63,0.18);
    color: var(--noir) !important;
}
.btn-outline-gold {
    background: transparent;
    color: var(--gold) !important;
    border: 1px solid var(--gold);
    border-radius: 100px;
    padding: 0.6rem 1.8rem;
}
.btn-outline-gold:hover {
    background: var(--gold-dim);
    transform: translateY(-2px);
    color: var(--gold-light) !important;
}
.btn-warning {
    background: #ffc107;
    color: #000 !important;
    border: none;
    border-radius: 6px;
    padding: 0.5rem 1rem;
    font-weight: 600;
    display: inline-flex; align-items: center; gap: 4px;
}
.btn-warning:hover {
    background: #ffb800;
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(255,193,7,0.3);
    color: #000 !important;
}
/* 2026-09-05: the top-nav "Admin" link used the shared .btn-warning (bright Bootstrap yellow) -
   never re-themed, stood out against the Atelier palette. Own class instead of restyling
   .btn-warning itself, since that class is also used by forum_topic.php's genuine warning
   buttons (unrelated semantics, not something this pass should recolor). */
.btn-admin-nav {
    background: var(--gold);
    color: var(--noir) !important;
    border: none;
    border-radius: 6px;
    padding: 0.5rem 1rem;
    font-weight: 600;
    display: inline-flex; align-items: center; gap: 4px;
}
.btn-admin-nav:hover {
    background: var(--gold-light);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(201,160,95,0.3);
    color: var(--noir) !important;
}

/* -- Cards / Surfaces --
   2026-09-05: Showroom Light trades the old dark-glow lift-on-hover treatment for hairline
   rules and a much quieter hover state - "hairline rules instead of borders" per the mockup. */
.luxury-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
    transition: box-shadow 0.4s var(--ease-luxury), border-color 0.4s var(--ease-luxury);
}
.luxury-card:hover {
    box-shadow: 0 8px 24px rgba(27,26,23,0.08);
    border-color: var(--stroke-gold);
}

/* Product & portfolio cards */
.product-card, .portfolio-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    overflow: hidden;
    transition: box-shadow 0.4s var(--ease-luxury), border-color 0.4s ease;
}
.product-card:hover, .portfolio-card:hover {
    box-shadow: 0 8px 24px rgba(27,26,23,0.10);
    border-color: rgba(147,113,63,0.35);
}
.p-image-wrap { overflow: hidden; position: relative; }
.p-image-wrap img {
    /* 2026-09-05: dropped the brightness/contrast/saturate dimming - furniture photography
       reads truest to color on a bright, neutral field (this direction's whole rationale),
       whereas the previous filter was tuned to sit well against a dark surround. */
    transition: transform 1.2s var(--ease-luxury);
}
.product-card:hover .p-image-wrap img,
.portfolio-card:hover .p-image-wrap img {
    transform: scale(1.06);
}

/* -- Forms -- */
.form-control, .form-select {
    background: var(--surface) !important;
    /* 2026-09-05: was rgba(27,26,23,0.14) - a near-black border at 14% opacity, tuned for a
       dark-on-light border back when --surface was Showroom Light's white/cream. Against
       Atelier's actual dark --surface, that same border is nearly invisible (dark-on-dark) -
       reported live as "we don't know where to type" on the empty Subject/Message fields in
       the contact modal. This affected every plain .form-control/.form-select sitewide, not
       just that one modal. var(--line) is the token every other bordered surface already uses
       and is genuinely visible against the dark surface. */
    border: 1px solid var(--line) !important;
    color: var(--ivory) !important;
    border-radius: var(--radius-sm) !important;
    padding: 0.75rem 1rem;
    font-family: var(--font-ui);
    font-size: 0.9rem;
    transition: border-color 0.3s ease, background 0.3s ease;
}
.form-control:focus, .form-select:focus {
    background: var(--surface) !important;
    border-color: var(--gold) !important;
    box-shadow: 0 0 0 3px rgba(147,113,63,0.12) !important;
    color: var(--ivory) !important;
}
::placeholder { color: var(--text-muted) !important; opacity: 0.7; }

/* -- Pagination --
   2026-09-05: never overridden anywhere in this codebase - every paginated list (gallery.php
   today, the Collections redesign next) inherited Bootstrap's stock blue .page-item.active, the
   one un-themed color left on the site. Active page gets the same two-accent gradient the rest
   of Atelier uses instead of introducing a third color. */
.pagination { --bs-pagination-focus-box-shadow: 0 0 0 3px rgba(147,113,63,0.18); }
.page-link {
    background: var(--surface);
    border-color: var(--line);
    color: var(--text-muted);
}
.page-link:hover {
    background: var(--surface);
    border-color: var(--gold);
    color: var(--gold);
}
.page-item.active .page-link {
    background: linear-gradient(135deg, var(--gold) 0%, var(--wine) 100%);
    border-color: transparent;
    color: var(--noir);
    font-weight: 600;
}
.page-item.disabled .page-link {
    background: var(--surface);
    border-color: var(--line);
    color: var(--text-muted);
    opacity: 0.5;
}

.form-label {
    font-family: var(--font-ui);
    font-size: 0.65rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 0.4rem;
}

/* -- Tables --
   2026-09-05: this overrides Bootstrap's .table-dark CSS variables, which covers most of what
   that class needs for a light theme - but Bootstrap's own .table-dark rule also sets a dark
   --bs-table-color/border baseline of its own that these variables don't reach everywhere, so a
   table using this class may still need a per-view look before it reads as fully "light" (see
   the file-header note on Bootstrap utility classes needing a separate pass). */
.table-dark {
    --bs-table-bg: transparent;
    --bs-table-striped-bg: rgba(27,26,23,0.02);
    --bs-table-hover-bg: rgba(147,113,63,0.06);
    color: var(--text-main);
    border-color: var(--stroke);
}
.table > thead > tr > th {
    font-family: var(--font-ui);
    font-size: 0.65rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--gold);
    border-bottom: 1px solid var(--stroke-gold);
    padding: 0.85rem 1rem;
}

/* -- Badges -- */
.badge {
    font-family: var(--font-ui);
    font-weight: 500;
    letter-spacing: 0.08em;
    border-radius: 4px;
    padding: 0.35em 0.65em;
}

/* Scroll reveal */
.sense-reveal {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.8s ease, transform 0.8s ease;
}
.sense-reveal.is-visible { opacity: 1; transform: translateY(0); }

/* -- Glass surface --
   2026-09-07 round 2 (3rd pass): "the login page and other modal pages must change to comply
   with the new color schemes" - was rgba(37,28,21,0.65), a literal from the old Atelier dark
   theme, never tokenized. Used by the Contact modal (.modal-content.glass-panel). Same
   taupe-deep "signature dark panel" treatment as the nav drawer/hero panel/cards - text inside
   needs to be cream, not the page's own dark default (same re-scoping reasoning documented on
   .sense-card in frontend_signature.css). */
.glass-panel {
    background: rgba(163,154,140,0.9);
    border: 1px solid var(--stroke);
    border-radius: var(--radius);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    color: var(--cream, #eee7d8);
}
.glass-panel .form-label,
.glass-panel .modal-body p { color: rgba(238,231,216,0.8); }
.glass-panel .form-control {
    background: rgba(238,231,216,0.08);
    border-color: rgba(238,231,216,0.2);
    color: var(--cream, #eee7d8);
}
.glass-panel .form-control::placeholder { color: rgba(238,231,216,0.45); }
.glass-panel .form-control:focus {
    background: rgba(238,231,216,0.12);
    border-color: var(--gold);
    color: var(--cream, #eee7d8);
}

/* -- Footer -- */
.sense-footer {
    margin-top: 0;
    /* 2026-09-05: was 36px/24px - with no social icons configured, .sense-footer-inner
       collapses to nothing, so this top padding alone was reading as a too-large gap between
       the ornament divider and the copyright line below it. Tightened proportionally. */
    padding: 18px 0 20px;
    border-top: 1px solid var(--stroke-gold);
    background: linear-gradient(180deg, rgba(147,113,63,0.04) 0%, transparent 100%);
    position: relative;
}
/* Decorative top ornament */
.sense-footer::before {
    content: '\2726';
    position: absolute;
    top: -0.7em;
    left: 50%;
    transform: translateX(-50%);
    color: var(--gold);
    font-size: 0.75rem;
    /* 2026-09-05: this used to carry `background: var(--bg); padding: 0 10px;` to patch over
       the border-top hairline right where the star sits - the intent was just to stop the line
       poking through the glyph's own letter-spacing, but the side effect was cutting a visible
       gap in the line, so the one hairline read as two disconnected segments (reported as
       "I see 2 lines"). Dropped the cutout - the star now sits directly on top of a single
       unbroken line instead of splitting it. */
    letter-spacing: 8px;
}
.sense-footer-inner {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 2vw;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 16px;
}
.sense-footer-brand {
    font-family: var(--font-display);
    font-size: 1.1rem;
    letter-spacing: 0.22em;
    color: var(--ivory);
    text-transform: uppercase;
}
.sense-footer-links {
    display: flex;
    gap: 24px;
    flex-wrap: wrap;
    justify-content: center;
    width: 100%;
}
.sense-footer-links a {
    font-family: var(--font-ui);
    font-size: var(--font-size-footer);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
    text-decoration: none;
    transition: color 0.3s ease;
}
.sense-footer-links a:hover { color: var(--gold); }

/* 2026-09-05: replaces the removed .sense-footer-links nav row - the site's top nav is always
   visible, so a duplicate link list at the bottom was redundant; this renders the company
   phone/email/address that SettingsHelper already provided to this file but nothing ever
   echoed. Own flex row (not just relying on .sense-footer-inner's) so it can collapse to a
   stacked column at a narrower point than the whole footer does. */
.sense-footer-info {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 8px 28px;
    width: 100%;
    font-family: var(--font-ui);
    font-size: var(--font-size-footer);
    color: var(--text-muted);
}
.sense-footer-info a { color: inherit; text-decoration: none; transition: color 0.3s ease; }
.sense-footer-info a:hover { color: var(--gold); }
.sense-footer-info-item { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.sense-footer-info-item i { color: var(--gold); font-size: 0.85em; }
@media (max-width: 575.98px) {
    .sense-footer-info { flex-direction: column; gap: 8px; }
    .sense-footer-info-item { white-space: normal; text-align: center; }
}

/* Social icons */
.sense-footer-socials { display: flex; gap: 16px; align-items: center; }
.sense-footer-socials a {
    color: var(--text-muted);
    font-size: 0.9rem;
    text-decoration: none;
    width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--stroke);
    border-radius: 50%;
    transition: color 0.3s ease, border-color 0.3s ease, transform 0.3s var(--ease-spring);
}
.sense-footer-socials a:hover {
    color: var(--gold);
    border-color: var(--stroke-gold);
    transform: translateY(-3px);
}

.sense-fineprint {
    width: 100%;
    text-align: center;
    font-family: var(--font-ui);
    font-size: var(--font-size-footer);
    letter-spacing: 0.12em;
    color: var(--text-muted); /* was rgba(...,0.28) - unreadably dim */
    padding-top: 16px;
    border-top: 1px solid var(--line);
    margin-top: 20px;
}

/* -- About Us image -- */
.luxury-image-wrapper {
    border-radius: 20px;
    overflow: hidden;
    max-height: 480px;
    position: relative;
}
.luxury-image-wrapper img {
    width: 100%;
    height: 100%;
    max-height: 480px;
    object-fit: cover;
    object-position: center;
    display: block;
}

/* -- About Us text -- */
.luxury-text {
    color: var(--text-muted, rgba(244,239,231,0.72));
    font-size: 0.97rem;
    line-height: 1.9;
    overflow-wrap: break-word;
    word-break: break-word;
    min-width: 0;
}
.luxury-subtitle {
    overflow-wrap: break-word;
    word-break: break-word;
    min-width: 0;
}

/* -- Contact map container -- */
.map-container {
    width: 100%;
    height: 440px;
    border-radius: 20px;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--line);
}
.map-container iframe {
    width: 100% !important;
    height: 100% !important;
    border: 0 !important;
    display: block;
    min-height: 440px;
}

/* -- Global overflow protection -- */
html, body { overflow-x: hidden; max-width: 100%; }
img { max-width: 100%; height: auto; }

/* -- Responsive -- */
/* 17" screen (~1280px) - keep content inside sense-max=1200px, no changes needed */
@media (max-width: 1279.98px) {
    .sense-hero-inner {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 991.98px) {
    :root { --nav-h: 58px; }
    .navbar-collapse {
        background: var(--surface);
        border: 1px solid var(--stroke-gold);
        border-radius: var(--radius-sm);
        padding: 16px;
        margin-top: 8px;
    }
    /* 2026-09-07: .nav-link's own rule is cream (correct for the fixed --taupe-deep navbar bar
       it normally sits in) but at this width the links move INSIDE .navbar-collapse instead,
       which is its own light --surface panel (confirmed live - cream-on-cream was invisible
       here). Dark text for this specific context only; the fixed bar above this breakpoint is
       unaffected. */
    .navbar-collapse .nav-link {
        color: var(--text-muted) !important;
        padding: 10px 8px !important;
    }
    .navbar-collapse .nav-link:hover,
    .navbar-collapse .nav-link.active {
        color: var(--text-main) !important;
    }
    .luxury-image-wrapper { max-height: 340px; }
    .luxury-image-wrapper img { max-height: 340px; }
    .map-container { height: 320px; }
    .map-container iframe { min-height: 320px; }
}

/* Tablet: ~768-991px */
@media (max-width: 767.98px) {
    h1 { font-size: clamp(1.8rem, 8vw, 3rem); }
    h2 { font-size: clamp(1.4rem, 6vw, 2rem); }
    .sense-footer-inner { flex-direction: column; text-align: center; gap: 12px; }
    .sense-footer-links { justify-content: center; }
    .luxury-image-wrapper { max-height: 260px; border-radius: 12px; }
    .luxury-image-wrapper img { max-height: 260px; }
    .map-container { height: 280px; border-radius: 12px; }
    .map-container iframe { min-height: 280px; }
    /* Prevent table overflow on small screens */
    .table-responsive { font-size: 0.82rem; }
    /* Fix any wide containers */
    .container { padding-left: 16px !important; padding-right: 16px !important; }
}

/* Small mobile: ~360-575px (Android 2016+ baseline) */
@media (max-width: 575.98px) {
    h1 { font-size: clamp(1.6rem, 7vw, 2.4rem); }
    h2 { font-size: clamp(1.2rem, 5vw, 1.8rem); }
    h3 { font-size: clamp(1rem, 4vw, 1.4rem); }
    .sense-stat-grid { grid-template-columns: 1fr 1fr; }
    .luxury-image-wrapper { max-height: 220px; border-radius: 10px; }
    .luxury-image-wrapper img { max-height: 220px; }
    .map-container { height: 240px; }
    .map-container iframe { min-height: 240px; }
    .sense-button { min-height: 46px; padding: 0 20px; font-size: 0.72rem; }
}