/* ===== frontend-body.css — OKAMI CMS public page body/content wrapper (V.104 CSS split) =====
   Split out of the former app.css. Theme presets, fluid CMS-content
   typography, the .frontend-body/.frontend-body__content wrapper, the
   frontend admin bar, and site-wide floating widgets (back-to-top,
   WhatsApp FAB, popup, inquiry-cart drawer) that render directly in
   resources/views/frontend/shell.php rather than inside the editable
   Header/Footer Layouts. Load between frontend-header.css and
   frontend-elements.css. */

/* V.063 — Universal UI/UX Kit V12 §26: 4 canonical theme presets + dark
   mode, applied to the public frontend only (scoped under `.frontend-body`
   — the admin panel's own dense UI is untouched by this round, same
   deliberate boundary the fluid type scale above already draws). Values are
   copied verbatim from the Kit's own `body[data-theme="..."]` blocks. Since
   every existing component already renders from these same --bg/--surface/
   --ink/--muted/--line/--accent/--soft/--shadow tokens (see the :root
   comment above), re-declaring just the tokens here reskins the whole site
   with no per-component overrides needed for the 3 light presets. Dark
   needs a few explicit component overrides too (inputs/panels/canvas-like
   surfaces) because some frontend rules use literal white/light colors
   instead of a token — those are called out below. Selected via Settings >
   Theme > "Color theme" (`theme_preset`, see SettingsController), applied
   as `data-theme` on `<body>` by FrontendController::themeCss(). Presets
   only replace accent/soft (light ones) or the full base palette (dark) —
   the owner's custom hex overrides in the same Theme tab still apply on
   top afterward, so a preset is a starting point, not a hard lock. */

.frontend-body[data-theme="blue"] { --accent: #285ff2; --soft: #edf2ff; }
.frontend-body[data-theme="emerald"] { --accent: #16855e; --soft: #eaf8f1; }
.frontend-body[data-theme="amber"] { --accent: #b56b00; --soft: #fff4df; }
.frontend-body[data-theme="dark"] {
  --bg: #0b1015;
  --surface: #121920;
  --ink: #edf2f6;
  --muted: #9aa7b2;
  --line: #29343e;
  --accent: #6f98ff;
  --soft: #18243d;
  --dark: #f2f5f8;
  --shadow: 0 20px 45px -12px rgba(0, 0, 0, .38);
}
.frontend-body[data-theme="dark"] input,
.frontend-body[data-theme="dark"] select,
.frontend-body[data-theme="dark"] textarea { background: var(--surface); color: var(--ink); border-color: var(--line); }
.frontend-body[data-theme="dark"] img { opacity: .92; }

/* V.096 — self-caught bug (DECISIONS.md #104): every "dark band" component
   (hero carousel, stats bar, footer, topbar) intentionally uses var(--dark)
   as its own background in the default theme, where --dark IS a real near-
   black. But the Dark preset above redefines --dark to a near-white ink
   value (it doubles as a text-ink token elsewhere) — so with Dark selected
   these bands were rendering near-white with their hardcoded white text
   still on top, making every heading in them unreadable. Pinning these five
   selectors to a real near-black here (independent of --dark) fixes it
   without touching --dark's other meaning. */
.frontend-body[data-theme="dark"] .builder-carousel,
.frontend-body[data-theme="dark"] .builder-stats-bar,
.frontend-body[data-theme="dark"] .frontend-body__footer,
.frontend-body[data-theme="dark"] .site-topbar,
.frontend-body[data-theme="dark"] .site-footer { background: #05070a; }

/* .frontend-body — merged below (this selector also carries the Phase 12
   real-shell margin reset a bit further down in this same file). */
.frontend-body h1, .frontend-body .fs-h1 { font-size: var(--fs-h1); line-height: 1.12; }
.frontend-body h2, .frontend-body .fs-h2 { font-size: var(--fs-h2); line-height: 1.18; }
.frontend-body h3, .frontend-body .fs-h3 { font-size: var(--fs-h3); line-height: 1.24; }
.frontend-body h4, .frontend-body .fs-h4 { font-size: var(--fs-h4); line-height: 1.3; }
.frontend-body h5, .frontend-body .fs-h5 { font-size: var(--fs-h5); line-height: 1.35; }
.frontend-body h6, .frontend-body .fs-h6 { font-size: var(--fs-h6); line-height: 1.4; }
.frontend-body .lead { font-size: var(--fs-lead); }
.frontend-body small, .frontend-body .fs-small { font-size: var(--fs-small); }

/* Round P (owner: "JECO Theme Blueprint" mockup sign-off — "yes, add
   Archivo") — real heading font, frontend only. Body copy stays Inter
   (untouched); every real heading tag AND the carousel/hero's own
   heading (a <h2> already covered by this same selector) gets the bolder
   industrial display face the reviewed mockup used. Admin panel
   typography is completely unaffected — this selector is scoped to
   .frontend-body, which only wraps the public site. */
.frontend-body h1, .frontend-body h2, .frontend-body h3,
.frontend-body h4, .frontend-body h5, .frontend-body h6 {
  font-family: 'Archivo', Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-weight: 800;
  letter-spacing: -.01em;
}

/* .frontend-body — merged from its 2 adjacent app.css rules (fluid
   type-scale base + the Phase 12 real-shell margin reset). */
.frontend-body { font-size: var(--fs-body); line-height: 1.65; margin: 0; }
.frontend-body__content { max-width: var(--container); margin: 0 auto; padding: 0 24px 64px; }

/* V.112 — "Boxed" site layout mode (owner: "header tum boxed bhi bana do,
   boxed version 100% body footer header same width"). `wide` (the default,
   unset Settings value) renders with none of this — `frontend/shell.php`
   simply doesn't emit `.site-boxed` at all, so wide mode is byte-identical
   to every prior version.
   In `boxed` mode, `frontend/shell.php` wraps `<header>`+`<main>`+`<footer>`
   (everything that needs to visually share one width) in this ONE element.
   `<header>`/`<main>`/`<footer>` are plain block elements with no width of
   their own, so they each resolve to exactly `.site-boxed`'s own width —
   genuinely the same computed width, not three sections independently
   centering to the coincidentally-equal `--container` token the way wide
   mode's `.site-topbar__inner`/`.site-nav`/`.frontend-body__content`/
   `.site-footer__*` already (independently) do. No `overflow:hidden` here
   deliberately — the header's mega-menu/dropdown and its `position:sticky`
   both need to be free to render/stick past this box's own edges; the
   "framed" look comes from the shadow/border alone, not corner-clipping. */
body.frontend-body[data-layout-mode="boxed"] { background: var(--bg); }
.site-boxed {
  max-width: var(--container-boxed);
  margin: 28px auto;
  box-shadow: 0 24px 60px -24px rgba(15, 23, 42, .22);
  border: 1px solid var(--line);
}
@media (max-width: 900px) {
  /* Owner ask is a desktop "framed card" pattern — a visible backdrop
     margin around a fixed-width column reads as broken, not "boxed", once
     the viewport itself is narrower than that column. Falls back to the
     exact same full-width rendering as `wide` mode below 900px (same
     breakpoint the header's own mobile nav collapse and the admin shell's
     sidebar collapse already use in this codebase). */
  .site-boxed { max-width: none; margin: 0; box-shadow: none; border: none; }
}

.frontend-popup { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; }
.frontend-popup__backdrop { position: absolute; inset: 0; background: rgba(0,0,0,.5); }
.frontend-popup__panel { position: relative; background: var(--surface); border-radius: var(--r); max-width: 480px; width: calc(100% - 48px); max-height: 80vh; overflow: auto; padding: 32px 24px 24px; }
.frontend-popup__close { position: absolute; top: 8px; right: 8px; width: 32px; height: 32px; border: none; background: transparent; font-size: 20px; /* decorative × glyph */ cursor: pointer; line-height: 1; }

/* V.110 orphan cleanup — `.frontend-empty-state` removed here: verified
   zero references anywhere in resources/views, app/**/*.php, or
   assets/js/**/*.js (the frontend's various real "nothing to show" states
   each use their own scoped `*--empty` class instead, e.g.
   `.builder-product-grid--empty`/`.builder-search-results--empty`). See
   `app/Support/UiKitAudit.php`'s live orphan report. */

/* V.065 — frontend admin bar (DECISIONS.md #085). Own sticky layer above
   the site header/topbar — `.has-adminbar` (set on `<body>` only when
   `FrontendController::adminBar()` returns non-null, i.e. a real logged-in
   admin is viewing the live site) nudges every other sticky frontend
   element down by this bar's own height so nothing overlaps it. Dark,
   deliberately distinct from the public site's own palette (same idea as
   WordPress's own admin bar) so it always reads as "this is admin chrome,
   not part of the page" regardless of which of the 4 theme presets is
   active. */
.oki-adminbar { position: sticky; top: 0; z-index: 200; background: #1b2530; color: #e6ebf0; font-size: var(--fs-13); }
.oki-adminbar__inner { max-width: var(--container); margin: 0 auto; padding: 0 16px; height: 40px; display: flex; align-items: center; gap: 4px; }
.oki-adminbar__brand { display: flex; align-items: center; gap: 8px; color: #fff; font-weight: 800; text-decoration: none; padding-right: 12px; }
.oki-adminbar__logo { width: 20px; height: 20px; border-radius: 5px; background: var(--accent); display: inline-flex; align-items: center; justify-content: center; font-size: var(--fs-11); font-weight: 900; }
.oki-adminbar__spacer { flex: 1; }
.oki-adminbar__link { color: #b9c3cd; text-decoration: none; padding: 0 12px; height: 40px; display: flex; align-items: center; font-weight: 600; }
.oki-adminbar__link:hover { color: #fff; background: rgba(255, 255, 255, .06); }
.oki-adminbar__link--edit { color: #fff; }
.oki-adminbar__link--btn { background: none; border: none; font: inherit; cursor: pointer; }
.oki-adminbar__logout { margin: 0; }
.oki-adminbar__user { color: #7f8b96; padding: 0 8px; font-size: var(--fs-12); white-space: nowrap; }
.frontend-body.has-adminbar .frontend-body__header,
.frontend-body.has-adminbar .site-header { top: 40px; }
@media (max-width: 640px) {
  .oki-adminbar__user { display: none; }
}

/* V.065 — Kit V12 §24 "Footer Back-to-top" (DECISIONS.md #086). */
.back-to-top {
  position: fixed; right: 20px; bottom: 20px; z-index: 90; width: 44px; height: 44px; border-radius: 50%;
  background: var(--accent); color: #fff; border: none; display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow); cursor: pointer; transition: opacity .15s, transform .15s;
}
.back-to-top:hover { transform: translateY(-2px); }
.back-to-top .builder-icon { width: 18px; height: 18px; }
.back-to-top .builder-icon svg { width: 100%; height: 100%; }
@media (prefers-reduced-motion: reduce) {
  .back-to-top { transition: none; }
}


/* V.073 ("Builder is King" mockup sign-off) — real site-wide floating
   WhatsApp button, a real `wa.me` deep link (see `FrontendController::
   whatsappFabUrl()`) — only rendered at all when the owner has set a
   real `inquiry_whatsapp_number` in Settings, never a fabricated/dead
   link. Stacked above `.back-to-top` (same corner, +58px) rather than
   sharing its position, since both can be visible on the same scroll
   position and must not overlap. */
.whatsapp-fab {
  position: fixed; right: 20px; bottom: 78px; z-index: 91; width: 48px; height: 48px; border-radius: 50%;
  background: #25d366; color: #fff; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 20px rgba(37, 211, 102, .4); text-decoration: none;
}
.whatsapp-fab svg { width: 24px; height: 24px; }
.whatsapp-fab:hover { background: #20bd5a; }

/* V.071 — Kit V12 §15 Advanced settings, Animation group. Initial hidden/
   offset state for any block carrying `data-pb-animate` (see
   BuilderRenderer::applyAdvanced()); `frontend-block-animate.js` adds
   `.pb-animate-in` the moment the block scrolls into view, which is what
   triggers the transition below. `prefers-reduced-motion` is handled in
   JS (skips the observer, adds `.pb-animate-in` immediately) — the base
   rule here still needs its own reduced-motion override so a slow/failed
   script load never leaves a block permanently invisible. */
[data-pb-animate="fade-in"] { opacity: 0; transition: opacity .6s ease; }
[data-pb-animate="fade-in"].pb-animate-in { opacity: 1; }
[data-pb-animate="fade-up"] { opacity: 0; transform: translateY(24px); transition: opacity .6s ease, transform .6s ease; }
[data-pb-animate="fade-up"].pb-animate-in { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  [data-pb-animate] { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* Round O — Inquiry Cart (owner: "prodct seelct add to inquieyry >> lead
   to inquiry cart cheqout and send as lead in one setep"). Floating badge
   + slide-in drawer, built mobile-responsive from the start per the
   lessons of the just-completed mobile audit above: no position:sticky
   inside the drawer, flex-wrap on button rows, min-width:0 on flex
   children, and the drawer itself becomes a full-width sheet under 560px
   instead of a fixed-width side panel that could overflow a small screen. */


/* Round O full re-audit found a real collision: this badge at the same
   bottom:20/right:20 spot as .back-to-top (44px) completely covered it —
   confirmed via a real Playwright bounding-box check (both rects
   overlapped almost exactly) and a screenshot showing back-to-top fully
   hidden underneath. Stacked above both existing bottom-right fixed
   buttons instead: .back-to-top sits at bottom:20 (44px tall, top edge
   ~64px), .whatsapp-fab sits at bottom:78 (48px tall, top edge ~126px)
   — this badge starts at bottom:140, clear of both, whether or not the
   WhatsApp FAB happens to be configured on this install. */
.oki-inquiry-cart__badge {
  position: fixed; right: 20px; bottom: 148px; z-index: 150;
  display: flex; align-items: center; justify-content: center;
  width: 54px; height: 54px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--accent, #285ff2); color: #fff; box-shadow: 0 8px 20px rgba(0,0,0,.18);
}
.oki-inquiry-cart__badge-icon svg { width: 22px; height: 22px; }
.oki-inquiry-cart__badge-count {
  position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 4px;
  border-radius: 999px; background: #fff; color: var(--accent, #285ff2); font-size: var(--fs-11); font-weight: 800;
  display: flex; align-items: center; justify-content: center; box-shadow: 0 1px 4px rgba(0,0,0,.25);
}
.oki-inquiry-cart__overlay {
  position: fixed; inset: 0; z-index: 160; background: rgba(0,0,0,.4);
}
.oki-inquiry-cart__drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 170;
  width: min(400px, 100vw); max-width: 100vw; background: var(--surface, #fff);
  box-shadow: -12px 0 30px rgba(0,0,0,.15); display: flex; flex-direction: column;
  min-width: 0;
}
.oki-inquiry-cart__head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 16px 18px; border-bottom: 1px solid var(--line);
}
.oki-inquiry-cart__head h3 { margin: 0; font-size: var(--fs-16); }
.oki-inquiry-cart__x { background: none; border: none; font-size: 22px; /* decorative × glyph */ line-height: 1; cursor: pointer; color: var(--muted); padding: 4px; }
.oki-inquiry-cart__body { flex: 1; overflow-y: auto; padding: 16px 18px; min-width: 0; }
.oki-inquiry-cart__empty { color: var(--muted); font-size: var(--fs-13_5); line-height: 1.6; text-align: center; padding: 30px 10px; }
.oki-inquiry-cart__list { display: flex; flex-direction: column; gap: 10px; }
.oki-inquiry-cart__row {
  display: flex; align-items: center; gap: 10px; padding: 10px; border: 1px solid var(--line); border-radius: var(--rs, 8px);
  flex-wrap: wrap; min-width: 0;
}
.oki-inquiry-cart__row-info { flex: 1; min-width: 120px; display: flex; flex-direction: column; gap: 2px; }
.oki-inquiry-cart__row-info strong { font-size: var(--fs-13); }
.oki-inquiry-cart__row-sku { font-size: var(--fs-11); color: var(--muted); }
.oki-inquiry-cart__row-qty { display: flex; align-items: center; gap: 8px; }
.oki-inquiry-cart__qtybtn {
  width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--line); background: var(--soft);
  cursor: pointer; font-size: var(--fs-15); line-height: 1; display: flex; align-items: center; justify-content: center;
}
.oki-inquiry-cart__remove { background: none; border: none; color: var(--muted); cursor: pointer; padding: 4px; }
.oki-inquiry-cart__remove svg { width: 16px; height: 16px; }
.oki-inquiry-cart__actions { display: flex; gap: 10px; margin-top: 16px; flex-wrap: wrap; }
.oki-inquiry-cart__actions .btn { flex: 1; min-width: 120px; }
.oki-inquiry-cart__back { background: none; border: none; color: var(--accent, #285ff2); cursor: pointer; font-size: var(--fs-13); padding: 0 0 12px; }
.oki-inquiry-cart__summary { list-style: none; margin: 0 0 16px; padding: 10px 12px; background: var(--soft); border-radius: var(--rs, 8px); font-size: var(--fs-12_5); display: flex; flex-direction: column; gap: 4px; }
.oki-inquiry-cart__form .builder-inquiry-form__grid { display: grid; grid-template-columns: 1fr; gap: 10px; }
.oki-inquiry-cart__sent { text-align: center; padding: 24px 10px; font-size: var(--fs-13_5); line-height: 1.6; }

@media (max-width: 560px) {
  .oki-inquiry-cart__drawer { width: 100vw; }
  .oki-inquiry-cart__badge { right: 14px; bottom: 136px; width: 48px; height: 48px; }
}
body.oki-inquiry-cart-open { overflow: hidden; }
/* Real bug found via Playwright mobile testing: `display: flex` on
   .oki-inquiry-cart__drawer (an author-stylesheet class rule) overrides
   the browser's own default `[hidden] { display: none }` UA rule, so the
   drawer stayed visible AND clickable underneath the badge even while
   its `hidden` attribute was set — silently blocking clicks on whatever
   sat behind it. Re-asserting `display: none` for the hidden state at
   higher specificity than the plain class rule fixes it. */
.oki-inquiry-cart__drawer[hidden], .oki-inquiry-cart__overlay[hidden] { display: none; }

/* V.107 — generic per-page-type "full width vs side panel" layout
   (owner: "Grid body can be full page half page side panel supported all
   elements 100% mobile first"). Used wherever `PageSettingsSchema`'s new
   `layout_mode` field is set to `sidebar` and the page type has real
   sidebar content to show (`PageTemplates::pageLayoutWrap()`) — currently
   Homepage's Featured Products grid, and Shop/Category's product grid.
   Deliberately separate from Shop's own pre-existing `.shop-layout`/
   `.shop-filters` pair (frontend-elements.css) — that one keeps its own
   sticky-sidebar behavior untouched by this round.

   Mobile-first: base rules are the single-column stack (main content
   first, side panel content BELOW it) — the natural DOM order already
   matches this, so no reordering is needed. The 2-column grid only
   applies from the same 861px breakpoint Shop's own sidebar already uses,
   for a consistent "sidebar appears" point across the whole site. */
.builder-page-layout { display: flex; flex-direction: column; gap: 28px; }
.builder-page-layout__main { min-width: 0; }
.builder-page-layout__aside { min-width: 0; }
@media (min-width: 861px) {
  .builder-page-layout { display: grid; grid-template-columns: 1fr 300px; align-items: start; gap: 28px; }
}
