:root[data-theme="light"] {
  --bg: #f7f7f9;
  --surface: #ffffff;
  --text: #1a1a1a;
  --muted: #6b7280;
  --border: #e5e7eb;
  --primary: #1d4ed8;
  --primary-contrast: #ffffff;
  --danger: #dc2626;
  --danger-dark: #991b1b;
  --success: #16a34a;
  --warning: #f97316;
  --warning-contrast: #ffffff;
}

/* Placeholder palette — swap these hex values for your exact brand colours
   once you share them, this is where the site's "dark" scheme lives. */
:root[data-theme="dark"] {
  --bg: #0f1420;
  --surface: #171d2b;
  --text: #e8eaf0;
  --muted: #9aa3b2;
  --border: #2a3244;
  --primary: #4f7cff;
  --primary-contrast: #ffffff;
  --danger: #f87171;
  --danger-dark: #b91c1c;
  --success: #4ade80;
  --warning: #fb923c;
  --warning-contrast: #1a1206;
}

* { box-sizing: border-box; }

html {
  height: 100%;
}

/* Sticky footer: body is a full-height column (header / main / footer) so
   that on pages with little content the footer sits at the bottom of the
   viewport instead of floating up under a short block of content. */
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  transition: background-color .15s ease, color .15s ease;
  overflow-x: hidden;
}

/* Site-wide link style: no underline, a subtle dim-on-hover instead. Opacity
   (rather than swapping to a fixed color) keeps this legible no matter what
   background a link sits on — hero banners, badges, nav bars, etc. Anything
   more specific (nav links, buttons styled as links) sets its own color and
   simply inherits this hover behaviour. */
a {
  color: var(--primary);
  text-decoration: none;
  transition: opacity .15s ease, color .15s ease;
}

a:hover {
  opacity: .72;
}

.site-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  padding: 1rem 2rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 500;
  gap: .5rem 1rem;
}

/* Window Controls Overlay title bar — only ever visible when app.js detects
   the app is installed and running in a Chromium browser that supports WCO
   (html.wco-active), so it's a safe no-op in every other context (regular
   browser tab, Firefox/Safari, mobile, not-yet-installed). Uses --bg rather
   than --surface so it visually reads as "the OS chrome above the app" —
   and because it's a plain theme variable, it re-colours instantly when the
   light/dark toggle runs, unlike the browser's own static manifest colour.
   The env() values come from the Window Controls Overlay API and describe
   the safe rectangle to draw in without overlapping the native minimize/
   maximize/close buttons; the px fallbacks only matter before app.js has
   run, and are harmless since the element is display:none until then. */
#wco-titlebar {
  display: none;
  position: fixed;
  top: 0;
  left: env(titlebar-area-x, 0);
  width: env(titlebar-area-width, 100%);
  height: env(titlebar-area-height, 33px);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  align-items: center;
  gap: .5rem;
  padding: 0 .75rem;
  font-size: .8rem;
  font-weight: 600;
  color: var(--text);
  z-index: 1000;
  -webkit-app-region: drag;
  app-region: drag;
}

html.wco-active #wco-titlebar {
  display: flex;
}

/* Push the real page content down below the overlay bar so nothing hides
   underneath it. */
html.wco-active .site-header {
  margin-top: env(titlebar-area-height, 33px);
  /* Sticky's `top` offset is measured from the viewport, independent of the
     margin above — without this the stuck header would settle at the very
     top of the screen, right under the fixed WCO title bar instead of
     below it. */
  top: env(titlebar-area-height, 33px);
}

.site-header .logo { font-weight: 700; font-size: 1.25rem; flex: 0 0 auto; }

/* The PProma mark is fill="currentColor", so its colour is set purely here —
   brand blue on light, and the same dashboard-blue (var(--primary)) on dark
   rather than switching to white/neutral — the logo and header icons should
   read as the same blue brand mark in both themes, matching the dashboard's
   icon tiles (.tile-btn .icon-svg), which are var(--primary) already. */
.brand-logo { color: #1D45A3; }
:root[data-theme="dark"] .brand-logo { color: var(--primary); }

/* Two logo variants sit in the header markup at once (see brand_logo() /
   brand_icon_mark() in helpers.php) — the full wordmark by default, and the
   icon-only mark swapped in on narrow screens where there isn't room for
   the full "pproma" text, rather than shrinking the wordmark down to
   illegible. */
.brand-logo-icon { display: none; }

.site-header nav { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.site-header nav a { color: var(--text); text-decoration: none; }
.site-header nav a:hover { color: var(--primary); }

/* Sits directly to the right of the logo, on the left side of the header —
   deliberately NOT centered/absolutely positioned, so it can never collide
   with the notification/theme/account icons on the right on narrow screens.
   Gap matches .site-header-right below so both icon groups read as the
   same visual rhythm instead of the left one looking noticeably tighter. */
.site-header-center {
  gap: .6rem !important;
}

/* Pushed to the far right; the logo + center icons naturally stay grouped
   together on the left because this is the only header child with auto
   margin pulling space toward itself. Gap explicitly matches
   .site-header-center rather than inheriting the generic `.site-header nav`
   1rem, which read as noticeably looser than the left icon group. */
.site-header-right {
  margin-left: auto;
  gap: .6rem;
}

.site-header .header-icon-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--primary);
  text-decoration: none;
  padding: .4rem;
  border-radius: 3px;
  line-height: 1;
}

.site-header .header-icon-link:hover {
  background: var(--bg);
}

/* Shared shape for every icon-only control on the right of the header
   (notifications, cart, theme toggle, language) — same height, padding and
   icon size so they all sit on one straight vertical line regardless of
   whether the markup is a <button> or an <a>, and regardless of an extra
   badge span inside (which can still grow the control's width without
   affecting its height/alignment). Colour matches the dashboard's icon
   tiles (.tile-btn .icon-svg) — var(--primary) — on light theme, rather
   than the neutral text colour, so the header and dashboard read as the
   same visual system there. Scoped as `.site-header .header-icon-btn`
   (not just `.header-icon-btn`) so it outweighs `.site-header nav a`'s
   color rule below for the <a>-tag instances of this class (cart-link) —
   otherwise that rule's higher specificity would silently win and leave
   just this one icon grey. */
.site-header .header-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  padding: 0 .3rem;
  margin: 0;
  background: none;
  border: none;
  color: var(--primary);
  cursor: pointer;
  text-decoration: none;
  border-radius: 3px;
  box-sizing: border-box;
  line-height: 1;
}

.site-header .header-icon-btn:hover {
  background: var(--bg);
}

/* Header dropdown menu icons (account menu, language menu, mobile nav
   panel — all rendered with the shared .user-menu-link row) match the
   dashboard-blue scheme in both themes; the row's own text stays
   var(--text) via .user-menu-link itself, only the icon recolours.
   var(--primary) resolves to a lighter blue (#4f7cff) in dark mode
   specifically so it still reads clearly there, rather than the low-
   contrast neutral look this used to revert to on dark theme. */
.user-menu-link .icon-svg {
  color: var(--primary);
}

/* These stay visible on every screen size, including mobile — they're
   quick access to Browse/Add Project (or the Paper/Material-stock
   equivalents), which is exactly the kind of action a mobile visitor is
   most likely to want in one tap, unlike the notification/cart/language/
   theme icons in .site-header-right, which move into the account dropdown
   below 768px instead (see #mobile-utility-row and app.js). No hamburger,
   no collapsing — just the plain icons, same as desktop. */

/* #notif-dropdown / #lang-menu-dropdown are inline-styled with a fixed
   pixel width sized for sitting directly under a header icon; once they're
   moved into #mobile-utility-row inside the (narrower) account dropdown on
   mobile (see app.js), cap them so they can't run off the edge of a small
   screen. */
@media (max-width: 480px) {
  #notif-dropdown, #lang-menu-dropdown {
    width: min(300px, 88vw) !important;
  }
}

@media (max-width: 560px) {
  .site-header { padding: .75rem 1rem; gap: .4rem .6rem; }
  .site-header nav { gap: .6rem; }
  .site-main { padding: 1.25rem; }
  .hero { padding: 2rem 1.25rem; }
  .hero h1 { font-size: 1.5rem; }
  .hero h2 { font-size: 1rem; }
  .brand-logo-full { display: none; }
  .brand-logo-icon { display: inline-block; }
}

/* flex:1 makes this stretch to fill any leftover vertical space in the
   body's flex column, so the footer never gets pulled up next to short
   content; min-height keeps that true even before flex has a chance to
   grow it (e.g. print/no-JS edge cases) by guaranteeing a tall baseline. */
.site-main { padding: 2rem; max-width: 960px; width: 100%; margin: 0 auto; flex: 1 0 auto; min-height: 80vh; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1.75rem;
}

/* Separates sections within a single "one card, multiple headings" page
   (Post a Project, project detail) so it reads as one document rather than
   several disconnected boxes, while still visually distinguishing sections. */
.card hr,
.section-divider {
  border: none;
  border-top: 1px solid var(--border);
  margin: 1.75rem 0;
}

.card h2 { margin-top: 0; }

/* Icon-on-top, label-below tile button used on the dashboard and admin
   overview screens (stat tiles, "My ..." shortcuts, quick actions) — keeps
   every tile the same shape regardless of what's inside, so the grid
   columns line up cleanly across sections. */
.tile-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  text-align: center;
  text-decoration: none;
  color: inherit;
}
.tile-btn .icon-svg { color: var(--primary); }
.tile-btn span { font-size: .85rem; color: var(--text); }

/* Dashboard "Browse" section specifically: a fixed 4 columns on wider
   screens, rather than the auto-fit column count the stats/quick-actions
   grids on the same page use — collapsing to 2 then 1 column as the
   screen narrows so tiles never get squeezed unreadably thin. */
.browse-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin-bottom: 1.75rem;
}
@media (max-width: 700px) {
  .browse-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 420px) {
  .browse-grid { grid-template-columns: 1fr; }
}

/* Selected-service badges on project cards (Printing / Binding / etc.) —
   a light tint of the theme's primary colour rather than a flat grey pill,
   so it reads as "part of this app" rather than a generic tag. */
.req-badge {
  font-size: .75rem;
  background: color-mix(in srgb, var(--primary) 12%, var(--surface));
  color: var(--primary);
  border: 1px solid color-mix(in srgb, var(--primary) 30%, var(--border));
  border-radius: 3px;
  padding: .15rem .6rem;
  display: inline-block;
}


/* Horizontal stage tracker — shows every trade the project needs as a step,
   with completed/current/upcoming states. */
.stage-tracker {
  display: flex;
  align-items: flex-start;
  gap: 0;
  margin: 1rem 0;
  overflow-x: auto;
  padding-bottom: .25rem;
}

.stage-tracker-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1 1 0;
  min-width: 90px;
  position: relative;
  text-align: center;
  /* Reset browser button chrome for the clickable <button> variant — the
     plain (non-clickable) steps are <div>s and unaffected by this. */
  background: none;
  border: none;
  font: inherit;
  padding: 0;
  margin: 0;
  color: inherit;
}

.stage-tracker-step.is-clickable {
  cursor: pointer;
}

.stage-tracker-step.is-clickable:hover .stage-tracker-dot {
  border-color: var(--primary);
  transform: scale(1.08);
}

.stage-tracker-step.is-clickable:hover .stage-tracker-label {
  color: var(--primary);
}

.stage-tracker-step:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 13px;
  left: 50%;
  width: 100%;
  height: 2px;
  background: var(--border);
  z-index: 0;
}

.stage-tracker-step.is-done:not(:last-child)::after {
  background: var(--success);
}

.stage-tracker-dot {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--success);
  z-index: 1;
  flex: 0 0 auto;
  transition: border-color .15s ease, transform .15s ease;
}

.stage-tracker-step.is-current .stage-tracker-dot {
  border-color: var(--primary);
  background: var(--primary);
}

.stage-tracker-step.is-done .stage-tracker-dot {
  border-color: var(--success);
  background: var(--surface);
}

.stage-tracker-label {
  font-size: .78rem;
  color: var(--muted);
  margin-top: .4rem;
  max-width: 100px;
}

.stage-tracker-step.is-current .stage-tracker-label {
  color: var(--primary);
  font-weight: 600;
}

.stage-tracker-step.is-done .stage-tracker-label {
  color: var(--text);
}

.stage-tracker-step.is-custom .stage-tracker-dot {
  border-style: dashed;
  border-color: var(--danger);
  color: var(--danger);
}

.stage-tracker-step.is-custom.is-current .stage-tracker-dot {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--surface);
}

.stage-tracker-step.is-custom .stage-tracker-label {
  color: var(--danger);
  font-style: italic;
}

label { display: block; font-size: .85rem; color: var(--muted); margin-bottom: .3rem; }

input, select, textarea {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: .6rem .75rem;
  width: 100%;
  margin-bottom: 1rem;
  font-size: 1rem;
}

/* The rule above is sized for text/select/textarea fields — applied
   unchanged to a checkbox it renders as a giant full-width padded
   rectangle instead of a normal ~1em box. Fixed once globally here rather
   than requiring every checkbox on every page to carry its own inline
   width:auto override (a few already do, from before this rule existed). */
input[type="checkbox"], input[type="radio"] {
  width: auto;
  padding: 0;
  margin: 0;
  vertical-align: middle;
}

button, .btn {
  display: inline-block;
  background: var(--primary);
  color: var(--primary-contrast);
  /* Transparent border of the same width as input/select/textarea's real
     border (see rule above) — without this, a button sitting next to a
     form field is ~2px shorter despite identical padding, since box-sizing:
     border-box counts the input's border inside its height and the
     button had none to match it. */
  border: 1px solid transparent;
  border-radius: 3px;
  padding: .6rem 1.1rem;
  cursor: pointer;
  font-size: 1rem;
  text-decoration: none;
  line-height: 1.5;
}

button:hover, .btn:hover { filter: brightness(1.08); }

/* Project status pills (Open/In progress/Completed/Cancelled — see
   project_status_color() in helpers.php). Overrides the base .btn text
   color (var(--primary-contrast), usually white) with black — the
   background colors here (success green, warning orange, danger red) are
   all light/mid-toned enough that black reads clearly on every one of
   them, unlike the default white which was made for --primary's blue. */
.status-badge {
  color: #000;
  white-space: nowrap;
}

/* Blends with the page instead of standing out — background matches the
   active theme (light/dark) rather than a fixed grey, with a border
   so it still reads as a button. Used for secondary actions like Print and
   Start Chat. */
button.btn-bg, .btn.btn-bg {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
}

/* Secondary action — replaces the flat grey (var(--muted)) background that
   used to be applied inline on Search/Clear/Edit/Decline-type buttons. White
   surface, brand-blue text and a matching blue border, so a secondary action
   reads as clearly clickable but visibly subordinate to the solid-blue
   primary button next to it. Uses var(--surface) rather than a hardcoded
   white so it stays legible on dark theme, where --surface is the dark card
   colour and --primary is the lighter blue. */
button.btn-secondary, .btn.btn-secondary {
  background: var(--surface);
  color: var(--primary);
  border: 1px solid var(--primary);
}

/* The base rule brightens on hover, which does nothing visible on a white
   surface — invert to the solid primary fill instead so there's clear
   feedback. */
button.btn-secondary:hover, .btn.btn-secondary:hover {
  background: var(--primary);
  color: var(--primary-contrast);
  filter: none;
}

/* Orange "caution" action — used for Hold, i.e. pausing a project. */
button.btn-warning, .btn.btn-warning {
  background: var(--warning);
  color: var(--warning-contrast);
}

/* Compact action buttons — used for the project page's top button row
   (Chat / Print / status / Edit / Start / Hold / Cancel) so a run of
   several buttons stays small and every one of them matches in size,
   regardless of which color/style class it's paired with. */
button.btn-sm, .btn.btn-sm {
  padding: .35rem .7rem;
  font-size: .82rem;
  border-radius: 3px;
}

/* Search/filter bar (see projects/index.php). A grid rather than flex:N
   ad hoc values on each field — grid-template-columns fills the row's
   full width predictably at any viewport, and the actions column gets an
   explicit track instead of being the one leftover item with no flex
   value (which previously meant it didn't grow/shrink with the rest of
   the row and could end up misaligned or oddly sized next to it).
   Two states only: one inline row on desktop, fully stacked on mobile —
   no intermediate tablet layout. */
.filter-bar {
  display: grid;
  width: 100%;
  box-sizing: border-box;
  grid-template-columns: 2fr 1fr 1fr 1fr auto;
  gap: .75rem;
  align-items: end;
  margin-bottom: 1.25rem;
  background: var(--bg);
  border-radius: 5px;
  /* Single source of truth for every control's height in this row —
     inputs, the select, and the buttons all reference the same value
     instead of each arriving at "about the same height" via their own
     padding/border math, which in practice still drifted by a few px
     and left mismatched corner radii (buttons default to 3px sitewide,
     inputs to 6px). */
  --control-height: 2.75rem;
  --control-radius: 6px;
}

.filter-bar .filter-field { min-width: 0; }

.filter-bar .filter-field input,
.filter-bar .filter-field select {
  height: var(--control-height);
  padding: 0 .75rem;
  margin-bottom: 0;
  border-radius: var(--control-radius);
  box-sizing: border-box;
  width: 100%;
}

/* Actions column has no <label>, so it has no label-height pushing it
   down the way every other column does — this placeholder keeps its
   button(s) sitting on the exact same baseline as the inputs beside it
   rather than being vertically centered against the taller label+input
   columns. */
.filter-bar .filter-actions-spacer {
  display: block;
  height: 1.2rem; /* matches label font-size(.85rem) + line-height + margin-bottom(.3rem) */
}

.filter-bar .filter-actions {
  display: flex;
  gap: .5rem;
}

.filter-bar .filter-actions button,
.filter-bar .filter-actions .btn {
  height: var(--control-height);
  padding: 0 1.1rem;
  border-radius: var(--control-radius);
  box-sizing: border-box;
  /* Strips the browser's native button chrome (which carries its own
     intrinsic sizing on top of our padding in some browsers) so height
     above is the only thing determining how tall the button renders. */
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid transparent;
  line-height: 1;
  display: inline-flex;
  align-items: center;
}

@media (max-width: 700px) {
  .filter-bar { grid-template-columns: 1fr; }
  .filter-bar .filter-actions-spacer { display: none; }
}

/* Post-project form (projects/create.php): every dropdown field sits in
   its own .field cell so grid-auto-flow naturally pairs two per row;
   anything that isn't a bare dropdown (text inputs, textareas, headings,
   the repeatable paper-items block, etc.) is wrapped in .field-full to
   span both columns and keep its existing full-width appearance. Each
   .toggle-section is a .field-grid in its own right (nested inside the
   outer one) so its dropdowns pair up independently of the rest of the
   form. */
.field-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1rem;
  align-items: start;
}

.field-grid > .field-full { grid-column: 1 / -1; }

.field-grid > .field,
.field-grid > .field-full {
  /* Grid items default to a min-width based on their content's intrinsic
     size — a <textarea> (sized in "cols", ~20 characters wide by default)
     or a <select> with a long option can therefore be wider than the
     column/row actually is, pushing the whole grid (and the card around
     it) wider than the page rather than wrapping/shrinking as width:100%
     below implies. min-width: 0 lets the item shrink to fit its track so
     width:100% on the field inside it is what actually governs the size. */
  min-width: 0;
}

.field-grid > .field select,
.field-grid > .field input,
.field-grid > .field textarea,
.field-grid > .field-full select,
.field-grid > .field-full input,
.field-grid > .field-full textarea { width: 100%; }

/* Textareas anywhere (not just inside .field-grid) can hit the same grid/
   flex "blowout" if their container is itself a grid or flex item — e.g.
   a .card on the project page, or a .field wrapper. min-width: 0 here
   makes width:100% (set on the base input/select/textarea rule above)
   reliable everywhere a textarea is used, not just in known-safe layouts. */
textarea { min-width: 0; max-width: 100%; }

@media (max-width: 700px) {
  .field-grid { grid-template-columns: 1fr; }
}

/* Repeatable "Add Paper" blocks (projects/create.php) — a thin top border
   between entries instead of each one being its own bordered/background
   box, so multiple papers read as one continuous list rather than a stack
   of separate cards. */
#paper-items-container .paper-item-block {
  padding: 1rem 0;
  border-top: 1px solid var(--border);
}

#paper-items-container .paper-item-block:first-child {
  padding-top: 0;
  border-top: none;
}

.section-toggle-row {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-bottom: 1rem;
}

.section-toggle-btn {
  background: var(--surface);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: .4rem 1rem;
  font-size: .9rem;
  cursor: pointer;
}

.section-toggle-btn.active {
  background: var(--primary);
  color: var(--primary-contrast);
  border-color: var(--primary);
}

.user-menu-link {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .5rem 1rem;
  color: var(--text);
  text-decoration: none;
  font-size: .9rem;
}

.user-menu-link:hover {
  background: var(--bg);
}

.site-footer {
  text-align: center;
  padding: 1.5rem 1rem;
  margin-top: 2rem;
  color: var(--muted);
  font-size: .85rem;
  border-top: 1px solid var(--border);
}

.site-footer a { color: var(--muted); }

.hero {
  background: linear-gradient(135deg, var(--primary), var(--success));
  color: #fff;
  padding: 3rem 2rem;
  text-align: center;
  margin-bottom: 2rem;
  width: 100vw;
  position: relative;
  left: 50%;
  margin-left: -50vw;
}

.hero-inner {
  max-width: 700px;
  margin: 0 auto;
}

.hero h1 {
  margin: 0 0 .5rem;
  font-size: 2.25rem;
}

.hero h2 {
  margin: 0 0 1.25rem;
  font-weight: 400;
  font-size: 1.15rem;
  opacity: .95;
}

.hero p {
  max-width: 560px;
  margin: 0 auto 1.5rem;
  line-height: 1.6;
  opacity: .95;
}

.hero .btn {
  background: #fff;
  color: var(--primary);
  font-weight: 600;
}

.hero .btn.btn-outline {
  background: transparent;
  color: #fff;
  border: 1px solid rgba(255,255,255,.7);
}

.benefits-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
  margin: 1.5rem 0 2rem;
  padding: 0;
}

.benefits-grid li {
  list-style: none;
}

.error { color: var(--danger); font-size: .85rem; margin: -.75rem 0 1rem; }

/* ===================== Chat / messages: threaded rows ===================== */

.chat-thread-box {
  margin-bottom: 1.1rem;
}

.chat-msg-row {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
}

.chat-avatar-wrap { flex: 0 0 auto; }

.chat-avatar,
.chat-avatar-fallback {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: block;
}

.chat-avatar { object-fit: cover; }

.chat-avatar-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--primary);
  color: var(--primary-contrast);
  font-weight: 700;
  font-size: .9rem;
}

.chat-msg-bubble {
  flex: 1 1 auto;
  min-width: 0;
}

.chat-msg-meta strong { color: var(--text); }

.chat-mention {
  color: var(--primary);
  font-weight: 600;
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  border-radius: 4px;
  padding: 0 .2rem;
}

.reply-btn {
  background: none;
  border: none;
  color: var(--primary) !important;
  text-decoration: none;
  padding: 0;
  font-size: .78rem;
  font-weight: 600;
  cursor: pointer;
  margin-top: .3rem;
  opacity: .9;
}
.reply-btn:hover { opacity: 1; }

/* Replies nest directly under their parent row, indented under the parent's
   avatar with a connecting line — matching the LinkedIn-style comment thread. */
.chat-replies {
  display: flex;
  flex-direction: column;
  gap: .65rem;
  margin: .65rem 0 0 18px;
  padding-left: 18px;
  border-left: 2px solid var(--border);
}

.chat-replies .chat-avatar,
.chat-replies .chat-avatar-fallback {
  width: 28px;
  height: 28px;
  font-size: .75rem;
}

.chat-thread-box .collapse-replies-btn {
  background: none;
  border: none;
  color: var(--muted);
  font-size: .8rem;
  cursor: pointer;
  padding: 0;
  margin: .5rem 0 0 18px;
}
.chat-thread-box .collapse-replies-btn:hover { color: var(--text); }

/* ===================== Chat composer: emoji + attach-file icon ===================== */

.chat-composer-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: .75rem;
  flex-wrap: wrap;
  position: relative;
}

.chat-composer-actions {
  display: flex;
  align-items: center;
  gap: .35rem;
  position: relative;
}

.chat-icon-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--text);
  width: 38px;
  height: 38px;
  border-radius: 3px;
  font-size: 1.05rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  padding: 0;
}
.chat-icon-btn:hover { background: var(--bg); }

.chat-file-input { display: none; }

.chat-file-chip {
  display: none;
  align-items: center;
  gap: .35rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: .25rem .7rem;
  font-size: .8rem;
  color: var(--text);
}

.chat-file-chip.is-visible { display: inline-flex; }

.chat-file-chip-remove {
  background: none;
  border: none;
  color: var(--danger);
  cursor: pointer;
  font-size: .85rem;
  padding: 0;
  line-height: 1;
}

.emoji-panel {
  display: none;
  position: absolute;
  bottom: 46px;
  left: 0;
  width: 236px;
  max-height: 190px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  box-shadow: 0 6px 20px rgba(0,0,0,.18);
  padding: .5rem;
  grid-template-columns: repeat(7, 1fr);
  gap: .15rem;
  z-index: 40;
}

.emoji-panel.is-open { display: grid; }

.emoji-panel-item {
  background: none;
  border: none;
  font-size: 1.15rem;
  cursor: pointer;
  border-radius: 3px;
  padding: .25rem 0;
  line-height: 1;
}
.emoji-panel-item:hover { background: var(--bg); }

/* ===================== @mention dropdown ===================== */

.mention-dropdown {
  display: none;
  position: absolute;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  box-shadow: 0 4px 16px rgba(0,0,0,.15);
  z-index: 45;
  max-height: 180px;
  overflow-y: auto;
}

.mention-dropdown-item {
  padding: .45rem .7rem;
  font-size: .88rem;
  cursor: pointer;
}
.mention-dropdown-item:hover,
.mention-dropdown-item.active { background: var(--bg); }

/* ===================== "Include a member" bar, above the chat composer ===================== */

.chat-members-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .6rem .9rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: .55rem .75rem;
  margin-bottom: .75rem;
}

.chat-members-bar-people {
  display: flex;
  align-items: center;
  gap: .4rem;
  flex-wrap: wrap;
}

.chat-members-bar-form {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin: 0;
  flex-wrap: wrap;
}

.chat-members-bar-form select {
  width: auto;
  min-width: 170px;
  margin: 0;
}

.chat-members-bar-form button {
  margin: 0;
}

/* ===================== Brand / social icons (theme-recolorable) ===================== */
/* These render via CSS mask so the SVG picks up var(--muted) / var(--primary)
   like any other themed element, instead of being stuck at a fixed color. */

.brand-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background-color: var(--muted);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: 55%;
  mask-size: 55%;
  transition: background-color .15s ease, transform .15s ease;
  text-decoration: none;
  flex: 0 0 auto;
}

.brand-icon:hover {
  background-color: var(--primary);
  transform: translateY(-1px);
}

.brand-icon.brand-icon-linkedin  { -webkit-mask-image: url('/assets/icons/brands/linkedin-in.svg'); mask-image: url('/assets/icons/brands/linkedin-in.svg'); }
.brand-icon.brand-icon-behance   { -webkit-mask-image: url('/assets/icons/brands/behance.svg');      mask-image: url('/assets/icons/brands/behance.svg'); }
.brand-icon.brand-icon-dribbble  { -webkit-mask-image: url('/assets/icons/brands/dribbble.svg');      mask-image: url('/assets/icons/brands/dribbble.svg'); }
.brand-icon.brand-icon-instagram { -webkit-mask-image: url('/assets/icons/brands/instagram.svg');     mask-image: url('/assets/icons/brands/instagram.svg'); }
.brand-icon.brand-icon-facebook  { -webkit-mask-image: url('/assets/icons/brands/facebook.svg');      mask-image: url('/assets/icons/brands/facebook.svg'); }
.brand-icon.brand-icon-x         { -webkit-mask-image: url('/assets/icons/brands/x-twitter.svg');     mask-image: url('/assets/icons/brands/x-twitter.svg'); }
.brand-icon.brand-icon-youtube   { -webkit-mask-image: url('/assets/icons/brands/youtube.svg');       mask-image: url('/assets/icons/brands/youtube.svg'); }
.brand-icon.brand-icon-whatsapp  { -webkit-mask-image: url('/assets/icons/brands/whatsapp.svg');      mask-image: url('/assets/icons/brands/whatsapp.svg'); }

.brand-icon-row {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
}

.brand-icon-sm {
  width: 26px;
  height: 26px;
}

.site-footer .brand-icon-row {
  justify-content: center;
  margin-top: .75rem;
}

/* ===================== Duotone UI icons (inlined SVGs) ===================== */
/* fill is set to currentColor at insertion time (see icon() in helpers.php),
   so these automatically match whatever color their container already uses —
   no per-icon color rules needed. This one rule gives every inlined icon its
   two-tone look. */

.icon-svg {
  display: inline-block;
  vertical-align: -0.15em;
  flex: 0 0 auto;
}

.icon-svg .fa-secondary { opacity: .45; }

/* ===================== Print styles ===================== */
/* Used by the "Print" button on a project page: hides interactive/nav UI
   (header nav icons, footer link list, buttons, forms, chat, proposals,
   tracker) so what comes out of the printer is just the project's
   requirements, framed by the PProma logo and the footer attribution line
   (kept visible — see .site-header/.site-footer below) so a printed sheet
   handed to a printer/binder/packager on the shop floor is still
   identifiable as coming from PProma — handy to hand to a printer/binder/
   packager on the shop floor. */
@media print {
  .no-print { display: none !important; }

  /* The header's sticky positioning is only useful for on-screen scrolling;
     printed pages have no scroll, so keep it in normal flow instead (sticky/
     fixed elements can be duplicated or clipped by browsers across printed
     pages). Same for the header's shadow/background chrome, which reads as
     on-screen UI rather than part of the document. */
  .site-header {
    position: static;
    border-bottom: 1px solid #ccd2dc;
    box-shadow: none;
    background: transparent !important;
  }

  /* Footer keeps only the copyright/attribution text (its nav links and
     social icons are marked .no-print above) — shown as a plain line under
     the content rather than the on-screen bordered/backgrounded footer. */
  .site-footer {
    position: static;
    border-top: 1px solid #ccd2dc;
    background: transparent !important;
    color: #55606e !important;
  }

  /* Force print-safe colours regardless of which theme (light/dark) was
     active on screen — without this, printing while in dark mode would
     use dark-theme border/text colours against the white print background,
     making tables and muted text hard to read or nearly invisible. */
  :root {
    --bg: #ffffff !important;
    --surface: #ffffff !important;
    --text: #111318 !important;
    --muted: #55606e !important;
    --border: #ccd2dc !important;
    --primary: #1d4ed8 !important;
  }

  body { background: #fff; color: #000; }

  .site-main {
    max-width: none;
    padding: 0;
    margin: 0;
  }

  .card {
    border: none;
    box-shadow: none;
    padding: 0;
    margin: 0 0 1rem;
  }

  a { color: #000; text-decoration: none; }

  table { page-break-inside: avoid; width: 100%; border-collapse: collapse; }
  table th, table td { border-bottom: 1px solid #ccd2dc; }
  table thead th {
    background: #f2f4f8 !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    color: #111318;
    font-weight: 700;
  }

  /* Branded print header/footer — hidden on screen, shown only on paper.
     See ppro_print_header()/ppro_print_footer() in helpers.php. */
  .print-doc-header {
    display: flex !important;
    justify-content: space-between;
    align-items: flex-end;
    border-bottom: 2px solid #1d4ed8;
    padding-bottom: 10px;
    margin-bottom: 18px;
  }
  .print-doc-logo {
    height: 34px;
    width: auto;
    display: block;
  }
  .print-doc-header .print-doc-meta {
    text-align: right;
    font-size: 11px;
    color: #55606e;
    line-height: 1.5;
  }
  .print-doc-title {
    font-size: 16px;
    font-weight: 700;
    color: #111318;
    margin: 0 0 14px;
  }
  .print-doc-footer {
    display: block !important;
    margin-top: 22px;
    padding-top: 10px;
    border-top: 1px solid #ccd2dc;
    text-align: center;
    font-size: 10.5px;
    color: #8a93a6;
  }
  .print-doc-footer a { color: #55606e; font-weight: 600; }

  @page { margin: 16mm 14mm; }
}

/* ===================== File picker (modern attach-files widget) ===================== */
/* Replaces the raw browser <input type=file> control: a styled trigger
   button plus a preview list of the currently-selected files (shown above
   the button), each removable before submitting. */

.file-picker-list {
  list-style: none;
  margin: 0 0 .6rem;
  padding: 0;
}

.file-picker-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  padding: .4rem .6rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  margin-bottom: .35rem;
  font-size: .85rem;
}

.file-picker-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-picker-remove {
  background: none;
  border: none;
  color: var(--danger);
  cursor: pointer;
  font-size: 1.1rem;
  line-height: 1;
  padding: 0 .3rem;
  flex: 0 0 auto;
}

.file-picker-remove:hover { filter: brightness(1.3); }

/* -------------------------------------------------------------------------
   Pricing page (/pricing)
   ---------------------------------------------------------------------- */

/* Free-tier "what you get for nothing" stats — plain icon + number, not a
   numbered list, since these two facts aren't a sequence. */
.pricing-stat-row {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 1rem;
}

.pricing-stat {
  flex: 1 1 220px;
  display: flex;
  gap: .75rem;
  align-items: flex-start;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1rem 1.1rem;
}

.pricing-stat-icon { color: var(--primary); flex: 0 0 auto; margin-top: .1rem; }
.pricing-stat .num { font-size: 1.15rem; font-weight: 700; }
.pricing-stat .sub { font-size: .8rem; color: var(--muted); margin-top: .1rem; }

/* Feature checklist shown once above the three plan cards — every plan
   unlocks the same full platform, so the difference between tiers is
   billing cadence and price, not features; repeating an identical list
   inside all three cards would just be noise. */
.pricing-feature-grid {
  display: block;
}

.pricing-feature-item {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .9rem;
  padding: .35rem 0;
}

.pricing-feature-icon { color: var(--success); flex: 0 0 auto; }

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1.25rem;
  margin: 1.5rem 0;
  align-items: stretch;
}

.pricing-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1.75rem 1.25rem 1.5rem;
  display: flex;
  flex-direction: column;
  text-align: center;
}

/* The one plan we steer people toward gets a lift and a brand-gradient cap —
   reusing the same gradient as .hero rather than a new colour, so the
   "recommended" cue reads as an extension of the app's own palette. */
.pricing-card.is-featured {
  border-color: var(--primary);
  box-shadow: 0 10px 26px rgba(0,0,0,.14);
  transform: translateY(-6px);
}

.pricing-card.is-featured::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: linear-gradient(90deg, var(--primary), var(--success));
  border-radius: 5px 5px 0 0;
}

.pricing-ribbon {
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: linear-gradient(90deg, var(--primary), var(--success));
  color: #fff;
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: .3rem .8rem;
  border-radius: 999px;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0,0,0,.22);
}

.pricing-plan-name {
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--muted);
  font-weight: 700;
}

.pricing-price {
  font-size: 2.1rem;
  font-weight: 800;
  margin: .5rem 0 0;
  line-height: 1.1;
}

.pricing-price small { font-size: .95rem; font-weight: 500; color: var(--muted); }

.pricing-billed { font-size: .8rem; color: var(--muted); margin-top: .3rem; }

.pricing-save {
  display: inline-block;
  margin-top: .6rem;
  background: var(--success);
  color: #fff;
  font-size: .72rem;
  font-weight: 700;
  padding: .2rem .55rem;
  border-radius: 3px;
}

/* A perforated-ticket rule instead of a plain line — a small nod to a
   printed stub tearing away from its counterfoil, fitting for a printing-
   industry tool without pulling in any new colour or asset. */
.pricing-divider {
  border: none;
  height: 1px;
  margin: 1.15rem 0;
  background-image: linear-gradient(90deg, var(--border) 55%, transparent 0%);
  background-size: 9px 1px;
  background-repeat: repeat-x;
}

.pricing-tagline {
  font-size: .85rem;
  color: var(--muted);
  flex: 1;
  margin: 0 0 1.15rem;
}

.pricing-card .btn,
.pricing-card .btn:disabled { width: 100%; }

@media (max-width: 560px) {
  .pricing-card.is-featured { transform: none; }
}

/* -------------------------------------------------------------------------
   News page (/news)
   ---------------------------------------------------------------------- */

.news-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 1.25rem;
}

.news-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  overflow: hidden;
  transition: box-shadow .15s ease, transform .15s ease;
}

.news-card:hover {
  box-shadow: 0 8px 20px rgba(0,0,0,.12);
  transform: translateY(-2px);
}

/* Wraps the thumbnail image so the video play-badge can be positioned
   over it. Position context only — the image itself still fills it. */
.news-card-media {
  position: relative;
}

.news-card-img {
  width: 100%;
  height: 150px;
  object-fit: cover;
  background: var(--bg);
  display: block;
}

.news-card-img-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
}

/* Round play-button badge shown on the thumbnail when NewsData.io
   supplies a video_url for the article, opening the video in a new tab
   independently of the article-link click target below it. */
.news-card-play {
  position: absolute;
  bottom: .5rem;
  right: .5rem;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(0,0,0,.65);
  color: #fff;
  text-decoration: none;
  transition: background .15s ease;
}

.news-card-play:hover { background: rgba(0,0,0,.85); }

.news-card-body {
  padding: .9rem 1rem 1rem;
  display: flex;
  flex-direction: column;
  flex: 1;
  text-decoration: none;
  color: var(--text);
}

.news-card-title {
  font-weight: 600;
  font-size: .95rem;
  line-height: 1.35;
  margin-bottom: .4rem;
}

.news-card-desc {
  font-size: .85rem;
  color: var(--muted);
  line-height: 1.5;
  margin: 0 0 .6rem;
  flex: 1;
}

.news-card-meta {
  display: flex;
  justify-content: space-between;
  gap: .5rem;
  font-size: .75rem;
  color: var(--muted);
  padding-top: .5rem;
  border-top: 1px solid var(--border);
}

/* Star rating display (member cards, project-page "already rated" state) —
   see star_rating() in helpers.php. Two identical rows of ★★★★★ stacked:
   a muted background row, and a coloured foreground row clipped to a
   percentage width so partial ratings (e.g. 4.3/5) render as a partially
   filled star rather than only ever whole stars. */
.star-rating {
  position: relative;
  display: inline-block;
  font-size: .95rem;
  line-height: 1;
  white-space: nowrap;
  vertical-align: middle;
}
.star-rating-track { color: var(--border); }
.star-rating-fill {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  white-space: nowrap;
  color: #f5a623;
}
.star-rating-count {
  font-size: .78rem;
  color: var(--muted);
  vertical-align: middle;
}

/* The 1-5 star picker used to submit a rating (Views/projects/show.php).
   Markup is five <input>/<label> PAIRS as flat siblings (not nested), in
   descending DOM order (5,4,3,2,1) with a shared `dir="rtl"` on the
   container — required for the trick below, not just a style choice:
   `~` only matches LATER siblings, so listing highest-to-lowest lets each
   label's hover reach every lower star after it in the DOM, while rtl
   flips the visual order back to the normal low-to-high left-to-right
   reading a star picker needs. */
.star-input { display: inline-flex; direction: rtl; }
.star-input input { position: absolute; opacity: 0; width: 0; height: 0; }
.star-input label {
  cursor: pointer;
  font-size: 1.3rem;
  line-height: 1;
  color: var(--border);
  margin: 0;
}
.star-input label:hover,
.star-input label:hover ~ label,
.star-input input:checked ~ label {
  color: #f5a623;
}

/* Member directory card (Views/members/index.php) — avatar + identity row
   up top, then the details a person scans for (role, location, rating,
   connection status), then a divider before the action row so the card
   reads as two clear zones: "who this is" and "what you can do about it",
   instead of one long stack of left-aligned lines. */
.member-card { padding: 1rem; }
.member-card-top {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: .6rem;
}
.member-avatar {
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
img.member-avatar { border: 1px solid var(--border); }
.member-avatar-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--primary);
  color: var(--primary-contrast);
  font-weight: 700;
}
.member-card-identity { min-width: 0; } /* lets long names/roles ellipsis instead of forcing the card wider */
.member-card-name {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.member-card-company, .member-card-role {
  font-size: .82rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.member-card-location { font-size: .78rem; color: var(--muted); margin-top: .3rem; }
.member-card-rating { margin-top: .4rem; }
.member-card-pill { margin-top: .4rem; }

/* Actions sit below a divider, evenly filling the row width (rather than
   ragged left-aligned button widths) so Message / Call / Connect always
   read as one balanced row regardless of which combination shows for a
   given card. */
.member-card-actions {
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
  margin-top: .75rem;
  padding-top: .75rem;
  border-top: 1px solid var(--border);
}
.member-card-actions .btn-sm {
  flex: 1 1 0;
  justify-content: center;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  white-space: nowrap;
}

/* Custom scrollbar: thin, theme-blue, square corners, transparent track —
   applied globally (any scrollable element, not just one page). Webkit
   (Chrome/Edge/Safari) uses the ::-webkit-scrollbar-* rules; Firefox uses
   the standard scrollbar-color/scrollbar-width properties, which can't
   express "square corners" or a separate width vs. height — Firefox's own
   thin scrollbar is the closest available match there. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--primary) transparent;
}
*::-webkit-scrollbar {
  width: 4px;
  height: 4px;
}
*::-webkit-scrollbar-track {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background: var(--primary);
  border-radius: 0;
}

/* FAQ page accordion (Views/faq.php) — plain <details>/<summary>, no JS,
   styled as a clean expand/collapse list rather than the browser's default
   triangle marker. */
.faq-item {
  border-bottom: 1px solid var(--border);
  padding: .6rem 0;
}
.faq-item:last-of-type { border-bottom: none; }
.faq-item > summary {
  cursor: pointer;
  font-weight: 600;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::after {
  content: '+';
  color: var(--primary);
  font-size: 1.2rem;
  font-weight: 400;
  flex-shrink: 0;
}
.faq-item[open] > summary::after { content: '\2212'; }
.faq-item p { margin: .5rem 0 0; color: var(--text); }

/* Language dropdown group headings ("International" / "Indian") — see
   render_lang_menu() in helpers.php. A second/later group label gets a
   divider above it so the two sections read as visually distinct. */
.lang-menu-group-label {
  padding: .3rem 1rem .45rem;
  color: var(--muted);
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .03em;
}
.lang-menu-group-label:not(:first-child) {
  margin-top: .3rem;
  border-top: 1px solid var(--border);
  padding-top: .55rem;
}

/* Baseline right-to-left support (Arabic) — flips text flow and the
   overall document direction via the <html dir="rtl"> attribute (see
   Views/layouts/main.php); most of this site's spacing is written with
   physical margin-left/margin-right in inline styles rather than logical
   properties, so fine-grained mirroring of every icon/button's position
   is a separate, larger pass if pixel-perfect RTL layout is wanted later
   — this covers correct, readable text direction throughout, which is
   the part that matters most.
   Duotone icons carry no inherent direction, but a few are visually
   directional (arrows) and should still point the way the icon itself
   implies, not the way the surrounding text flows — deliberately left
   unflipped here for exactly that reason. */
:root[dir="rtl"] { text-align: right; }
:root[dir="rtl"] input, :root[dir="rtl"] textarea, :root[dir="rtl"] select { text-align: right; }

/* The client asked for Arabic (and other RTL languages) to get correctly
   right-aligned, right-to-left TEXT without the rest of the interface's
   layout rearranging — e.g. header icons swapping sides, dropdown panels
   detaching from the buttons that open them, or multi-column form grids
   reordering. dir="rtl" on <html> mirrors flex/grid item order as well as
   text, which is what was causing that: a flex row's items reverse under
   RTL even though anything positioned with physical left/right or floated
   does NOT (those are unaffected by direction), so a trigger icon would
   move to the opposite side while the menu anchored under it stayed put.
   Pinning direction back to ltr on the structural chrome/grid containers
   below stops their item order from mirroring, while text inside them
   still renders RTL correctly because direction is set again one level
   further in on the actual text-bearing elements. Add any other
   multi-column/flex container here if it's seen to reorder under Arabic. */
:root[dir="rtl"] .site-header,
:root[dir="rtl"] .site-header-center,
:root[dir="rtl"] .site-header-right,
:root[dir="rtl"] .site-footer,
:root[dir="rtl"] .field-grid {
  direction: ltr;
}
/* Earlier this also set direction:rtl back on every descendant of
   .site-header/.site-footer (".site-header *"), meant to keep nav text
   reading right-to-left. That selector has the SAME specificity as the
   rule above it (one :root[attr] + one class each; "*" adds nothing), so
   on .site-header-right itself — which is both "pin to ltr" above AND a
   descendant matched by "*" here — the later rule won the tie and flipped
   it straight back to rtl, reversing the icon row and its dropdown again.
   Dropped rather than re-targeted: header/footer only hold short nav
   labels and icons, no typed input, so the browser's own bidi handling
   renders Arabic correctly without an explicit direction here — only
   .field-grid actually has user-typed text/inputs that need it. */
:root[dir="rtl"] .field-grid label,
:root[dir="rtl"] .field-grid p,
:root[dir="rtl"] .field-grid span,
:root[dir="rtl"] .field-grid input,
:root[dir="rtl"] .field-grid select,
:root[dir="rtl"] .field-grid textarea {
  direction: rtl;
}
