/* Encom skin for the self-hosted Postiz — eDEX-UI "white" theme (pale cyan-white on navy-black),
   lifted from master-control/packages/dashboard/src/grid.css. Injected by skin/nginx.conf before
   </head>, so it loads after Postiz's own stylesheets and wins on equal specificity. Postiz is
   themed through CSS custom properties; we remap them and touch classes only where a token
   doesn't reach (logo, primary button, fonts). Updating the Postiz image never touches this file. */

@font-face { font-family: "Share Tech Mono"; src: url(/encom/fonts/share-tech-mono.woff2) format("woff2"); font-weight: 100 900; font-display: swap; }
@font-face { font-family: "Michroma"; src: url(/encom/fonts/michroma.woff2) format("woff2"); font-weight: 100 900; font-display: swap; }
/* Postiz's body font is self-hosted "Plus Jakarta Sans" in per-weight subsets. A later face with
   the same family name and a full weight range outranks them, so every Jakarta element becomes
   Share Tech Mono without touching a single Postiz class. */
@font-face { font-family: "Plus Jakarta Sans"; src: url(/encom/fonts/share-tech-mono.woff2) format("woff2"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Plus Jakarta Sans"; src: url(/encom/fonts/share-tech-mono.woff2) format("woff2"); font-weight: 100 900; font-style: italic; font-display: swap; }

:root {
  --encom-bg: #050a12;
  --encom-panel: #080e1a;
  --encom-panel2: #0b1322;
  --encom-glow-rgb: 170, 207, 209;
  --encom-mcp: #aacfd1;
  --encom-mcp2: #e6f7f8;
  --encom-mcp3: #cfe6e8;
  --encom-text: #e8f4f5;
  --encom-muted: #6f9094;
  --encom-frame: rgba(170, 207, 209, 0.55);
  --encom-frame-dim: rgba(170, 207, 209, 0.22);
  --encom-alert: #ff3b1e;
  --encom-ok: #39d98a;
  --encom-warn: #ffd166;
}

/* Both Postiz modes render the white theme — the sun/moon toggle becomes a no-op by design. */
:root .dark, :root .light {
  --new-back-drop: #020509;
  --new-settings: var(--encom-panel2);
  --new-border: var(--encom-frame-dim);
  --new-bgColor: var(--encom-bg);
  --new-bgColorInner: var(--encom-panel);
  --new-sep: var(--encom-frame-dim);
  --new-bgLineColor: var(--encom-bg);
  --new-textItemFocused: var(--encom-mcp2);
  --new-textItemBlur: var(--encom-muted);
  --new-boxFocused: var(--encom-mcp);
  --new-textColor: 232 244 245;
  --new-blockSeparator: var(--encom-panel2);
  --new-btn-simple: var(--encom-panel2);
  --new-btn-text: var(--encom-text);
  --new-btn-primary: #16454c;
  --new-ai-btn: #2a6f78;
  --new-box-hover: var(--encom-panel2);
  --new-table-border: var(--encom-frame-dim);
  --new-table-header: var(--encom-panel2);
  --new-table-text: var(--encom-muted);
  --new-table-text-focused: var(--encom-mcp2);
  --new-small-strips: var(--encom-panel2);
  --new-big-strips: var(--encom-panel);
  --new-col-color: var(--encom-panel2);
  --new-menu-dots: var(--encom-muted);
  --new-menu-hover: var(--encom-mcp2);
  --menu-shadow: 0 8px 30px 0 rgba(0, 0, 0, 0.6), 0 0 0 1px var(--encom-frame-dim);
  --popup-color: rgba(5, 10, 18, 0.7);
  --border-preview: var(--encom-frame-dim);
  --preview-box-shadow: none;
  /* legacy tokens still used by older components */
  --color-primary: var(--encom-bg);
  --color-secondary: var(--encom-panel);
  --color-third: var(--encom-panel);
  --color-text: var(--encom-text);
  --color-forth: #16454c;
  --color-seventh: #2a6f78;
  --color-gray: var(--encom-muted);
  --color-input-text: var(--encom-muted);
  --color-custom4: var(--encom-mcp);
  --color-custom7: #2a6f78;
  --color-custom11: var(--encom-mcp);
  --color-custom12: var(--encom-mcp3);
  --color-custom17: var(--encom-text);
  --color-custom18: var(--encom-muted);
  --color-custom28: var(--encom-mcp3);
  --color-custom29: var(--encom-panel2);
  --color-custom30: #16454c;
  --color-custom41: var(--encom-mcp3);
  --color-custom45: #2a6f78;
}

html, body { background: var(--encom-bg) !important; color: var(--encom-text); }
body { font-family: "Share Tech Mono", "Menlo", monospace; }
h1, h2, h3, [class*="text-[24px]"], [class*="text-[20px]"] { font-family: "Michroma", "Futura", sans-serif; letter-spacing: 0.02em; }
a { color: var(--encom-mcp2); }
::selection { background: rgba(var(--encom-glow-rgb), 0.35); }

/* eDEX dot grid + faint scanlines */
body::before { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image: radial-gradient(rgba(var(--encom-glow-rgb), 0.07) 1px, transparent 1px); background-size: 26px 26px; }
/* Keep the scanlines beneath the interface so they cannot stripe brand artwork. */
body::after { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.16) 0 1px, transparent 1px 3px); }

/* ——— chamfered panels (the Grid's augmented-ui register, master-control grid.css:150) ———
   The Grid clips .panel itself. We cannot: Postiz hangs dropdowns, date pickers and the emoji
   picker inside these same containers, and a clip-path on the parent would guillotine them
   (#24: "no clip-path on inputs/menus"). So the two-layer chamfer is drawn on ::before/::after
   underneath the content instead — identical geometry, nothing clipped.
   .bg-newBgColorInner is Postiz's own panel class, used by the calendar cards, settings boxes
   and launches, so this reaches the whole app rather than one screen. */
:root { --encom-chamfer: 14px; --encom-chamfer-in: 13.2px; }

/* :not([class~="fixed"]) everywhere below: the channel-row ⋮ dropdown (launches/menu.tsx) is
   `fixed bg-newBgColorInner shadow-menu` positioned by inline top/left from the trigger's
   viewport rect. Forcing it relative re-flows it INTO the row (the row visibly "unfolds"),
   turns the inline top into a 900px+ downward shift, and the transparent ground erases what
   little still paints — the invisible-ellipsis-menu bug, 2026-08-25. Fixed overlays keep
   their own positioning; §12 gives them their panel look instead. */
.bg-newBgColorInner:not([class*="h-["]):not([class~="fixed"]),
[class*="lg:w-[600px]"][class*="rounded-"] {
  position: relative;
  background-color: transparent !important;
  border-radius: 0 !important;
  border-color: transparent !important;
}
.bg-newBgColorInner:not([class*="h-["]):not([class~="fixed"])::before,
[class*="lg:w-[600px]"][class*="rounded-"]::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(160deg, var(--encom-frame), var(--encom-frame-dim) 55%, var(--encom-frame));
  clip-path: polygon(var(--encom-chamfer) 0, 100% 0, 100% calc(100% - var(--encom-chamfer)),
                     calc(100% - var(--encom-chamfer)) 100%, 0 100%, 0 var(--encom-chamfer));
}
.bg-newBgColorInner:not([class*="h-["]):not([class~="fixed"])::after,
[class*="lg:w-[600px]"][class*="rounded-"]::after {
  content: ""; position: absolute; inset: 1px; z-index: 0; pointer-events: none;
  background: var(--encom-panel);   /* = grid.css --panel #080e1a in theme white */
  clip-path: polygon(var(--encom-chamfer-in) 0, 100% 0, 100% calc(100% - var(--encom-chamfer-in)),
                     calc(100% - var(--encom-chamfer-in)) 100%, 0 100%, 0 var(--encom-chamfer-in));
}
/* content has to clear the two painted layers */
.bg-newBgColorInner:not([class*="h-["]):not([class~="fixed"]) > *,
[class*="lg:w-[600px]"][class*="rounded-"] > * { position: relative; z-index: 1; }

/* Fixed-height panels keep the frame without the chamfer, so they still read as Grid furniture */
.bg-newBgColorInner[class*="h-["] {
  background-color: var(--encom-panel) !important;
  border: 1px solid var(--encom-frame-dim) !important;
  border-radius: 0 !important;
}

/* Form controls keep square corners and a lit frame, but never a chamfer — a clipped input
   corner eats the caret and the select arrow. */
input, textarea, select, .react-tags, .react-tags__combobox {
  border-radius: 0 !important;
  background-color: var(--encom-panel2) !important;
  border: 1px solid var(--encom-frame-dim) !important;
}
input:focus, textarea:focus, select:focus {
  border-color: var(--encom-frame) !important;
  box-shadow: 0 0 10px rgba(var(--encom-glow-rgb), 0.18);
}

/* Panel headers in the Grid's voice: Michroma, wide tracking, rule to the right (grid.css .ph) */
.bg-newBgColorInner > h1, .bg-newBgColorInner > h2, .bg-newBgColorInner > h3 {
  font-family: "Michroma", "Futura", sans-serif;
  letter-spacing: 0.28em; text-transform: uppercase; color: var(--encom-mcp2);
  display: flex; align-items: center; gap: 8px;
}
.bg-newBgColorInner > h1::after, .bg-newBgColorInner > h2::after, .bg-newBgColorInner > h3::after {
  content: ""; flex: 1; min-width: 12px; height: 1px; background: var(--encom-frame-dim);
}

/* Primary actions: outlined glow instead of Postiz purple */
.bg-btnPrimary, [class*="bg-btnPrimary"] { background: rgba(var(--encom-glow-rgb), 0.14) !important;
  box-shadow: inset 0 0 0 1px var(--encom-frame), 0 0 12px rgba(var(--encom-glow-rgb), 0.18); color: var(--encom-mcp2) !important; }
.bg-btnPrimary:hover, [class*="bg-btnPrimary"]:hover { background: rgba(var(--encom-glow-rgb), 0.24) !important; }
[class*="rounded-"] { --tw-ring-color: var(--encom-frame-dim); }
input, textarea, select { caret-color: var(--encom-mcp2); }
input:focus, textarea:focus, select:focus { outline-color: var(--encom-frame) !important; }

/* Logo: hide Postiz's inline "P" and paint the Encom disc in its slot (#left-menu is a stable id) */
#left-menu > div > svg:first-child { display: none !important; }
#left-menu > div::before { content: ""; display: block; width: 60px; height: 60px; margin: 8px auto 0; flex: 0 0 60px;
  background: url(/encom/logo.svg) center / 60px 60px no-repeat; filter: drop-shadow(0 0 6px rgba(var(--encom-glow-rgb), 0.45)); }

/* Login page: Postiz's marketing column (testimonials) is noise on an internal tool */
[class*="auth"] [class*="testimonial"], .testimonials { display: none !important; }

/* ---- Hard-coded Tailwind colours Postiz uses outside the token system (login/auth pages, a few
   panels). Attribute-contains selectors avoid escaping the brackets. Greys → our navy scale,
   purples → teal, so no purple/grey survives an image update that keeps these class names. */
[class*="bg-[#0E0E0E]"], [class*="bg-[#0B0A0A]"], [class*="bg-[#000000]"], [class*="bg-[#121212]"] { background-color: var(--encom-bg) !important; }
[class*="bg-[#1A1919]"], [class*="bg-[#2A2929]"] { background-color: var(--encom-panel) !important; }
[class*="border-[#1F1F1F]"], [class*="border-[#2A2929]"], [class*="border-[#2b2a2a]"], [class*="border-[#000]"] { border-color: var(--encom-frame-dim) !important; }
[class*="bg-[#612BD3]"], [class*="bg-[#612bd3]"], [class*="bg-[#9333ea]"], [class*="bg-[#AA0FA4]"] { background-color: #16454c !important; box-shadow: inset 0 0 0 1px var(--encom-frame); }
[class*="text-[#612BD3]"], [class*="text-[#612bd3]"], [class*="text-[#B69DEC]"], [class*="text-[#FC69FF]"] { color: var(--encom-mcp2) !important; }
[class*="border-[#612BD3]"], [class*="border-[#622FF6]"], [class*="border-[#618DFF]"], [class*="border-[#FC69FF]"] { border-color: var(--encom-frame) !important; }
[class*="text-[#D1D1D1]"], [class*="text-[#A3A3A3]"] { color: var(--encom-muted) !important; }
[class*="from-[#622aff]"] { --tw-gradient-from: #16454c !important; } [class*="to-[#8b5cf6]"] { --tw-gradient-to: #2a6f78 !important; }

/* Auth pages: hide the marketing column, swap the Postiz wordmark for the Encom disc + name */
[class*="pt-[88px]"][class*="text-[36px]"] { display: none !important; }
[class*="lg:w-[600px]"] > [class*="max-w-[440px]"] > svg:first-child { display: none !important; }
/* The auth column has 440px of width, so it gets the full wordmark rather than mark + text set
   in Michroma — the wordmark is the letterforms, and typesetting the name beside it said the
   same thing twice in two different voices. */
[class*="lg:w-[600px]"] > [class*="max-w-[440px]"]::before { content: ""; display: block; height: 62px; width: 240px;
  background: url(/encom/wordmark.svg) left center / 240px auto no-repeat;
  filter: drop-shadow(0 0 8px rgba(var(--encom-glow-rgb), 0.4)); }

/* Compliance footer injected by nginx (privacy link + YouTube API Services branding) */
#encom-foot { position: fixed; left: 0; right: 0; bottom: 0; z-index: 2147483100; display: flex; flex-wrap: wrap; gap: 0 18px; align-items: center; justify-content: center;
  padding: 6px 16px; font: 12px/1.6 "Share Tech Mono", "Menlo", monospace; color: var(--encom-muted);
  background: var(--encom-bg); border-top: 1px solid var(--encom-frame-dim); }
#encom-foot a { color: var(--encom-mcp); text-decoration: underline; text-underline-offset: 3px; }
#encom-foot .yt { display: inline-flex; align-items: center; gap: 6px; color: var(--encom-text); }
#encom-foot img { height: 40px; min-height: 40px; width: auto; flex-shrink: 0;
  object-fit: contain; border-radius: 0; clip-path: none; filter: none; }
/* The official PNG includes transparent clear space: its visible 579px-high artwork occupies
   579/1075 of the canvas. A 40px image renders the unchanged icon at 21.54px, above the report's
   20px minimum. Keep the image and its clear space at this size on phones too. */

/* Phone widths (#24 verification): the footer's six items wrap 2 → 3 lines instead of one,
   which pushed its real height past what a fixed padding-bottom reservation could buy back —
   `min-h-screen` on the auth page only holds its box AT 100vh while content+padding stays
   under that ceiling, so past a small threshold more padding just grows the (invisible,
   scrolled-past) document instead of shifting the centred content up. Tighter type and gaps
   reduce wrapping while the branding keeps its size; skin.js measures the resulting footer
   height for the content and rail reservation below. */
@media (max-width: 480px) {
  #encom-foot { gap: 2px 10px; padding: 4px 10px; font-size: 10px; line-height: 1.35; }
}

/* ——— no light surfaces ———
   body::after paints scanlines over the whole document. Over --encom-bg that is the eDEX
   register; over a white button it looks like a rendering fault. Postiz's OAuth provider
   buttons are `bg-white`, so they get the panel treatment and the striping stops being wrong.
   Google's brand guidance permits a dark sign-in button, and the G glyph keeps its colour. */
[class*="bg-white"] {
  background-color: var(--encom-panel2) !important;
  color: var(--encom-text) !important;
  border: 1px solid var(--encom-frame) !important;
  border-radius: 0 !important;
  box-shadow: inset 0 0 24px rgba(var(--encom-glow-rgb), 0.06);
}
[class*="bg-white"]:hover { background-color: var(--encom-panel) !important;
  box-shadow: inset 0 0 24px rgba(var(--encom-glow-rgb), 0.12), 0 0 14px rgba(var(--encom-glow-rgb), 0.15); }
[class*="text-[#0E0E0E]"], [class*="text-[#0e0e0e]"] { color: var(--encom-text) !important; }

/* ═══ THE GRID REGISTER, APPLIED APP-WIDE ═══════════════════════════════════════════════
   Derived from an inventory of all 263 Postiz frontend components rather than from the one
   screen an unauthenticated session can see. Counts below are occurrences in that source. */

/* 1. Square everything. Postiz uses 405+ rounded-* utilities; the Grid has no rounded corner
      anywhere — it is chamfers and right angles. This single rule does more for the resemblance
      than any other. rounded-full is spared: those are avatars.
      Matching `rounded-` rather than `rounded-[` on purpose — the directional variants
      (rounded-e-[8px], rounded-s-, rounded-tl- …) do not contain the substring `rounded-[`, so
      they were sailing through: that is why the active tab in Settings still had a rounded end. */
[class*="rounded-"]:not([class*="rounded-full"]) { border-radius: 0 !important; }

/* 2. Every border token resolves to the frame colour, so one hue outlines the whole app
      (border-fifth ×36, border-newTableBorder ×34, border-tableBorder ×29, border-newBorder ×27,
      border-customColor6 ×13, border-newColColor ×11). */
[class*="border-fifth"], [class*="border-newBorder"], [class*="border-tableBorder"],
[class*="border-newTableBorder"], [class*="border-customColor6"], [class*="border-newColColor"],
[class*="border-sixth"] { border-color: var(--encom-frame-dim) !important; }

/* 3. The other panel grounds. bg-newBgColorInner was already chamfered; these are the ones
      the settings, table and column surfaces use. Same two-layer treatment. */
.bg-sixth:not([class*="h-["]),
.bg-newBgColorInnerInner:not([class*="h-["]) {
  position: relative; background-color: transparent !important; border-color: transparent !important;
}
.bg-sixth:not([class*="h-["])::before,
.bg-newBgColorInnerInner:not([class*="h-["])::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(160deg, var(--encom-frame), var(--encom-frame-dim) 55%, var(--encom-frame));
  clip-path: polygon(var(--encom-chamfer) 0, 100% 0, 100% calc(100% - var(--encom-chamfer)),
                     calc(100% - var(--encom-chamfer)) 100%, 0 100%, 0 var(--encom-chamfer));
}
.bg-sixth:not([class*="h-["])::after,
.bg-newBgColorInnerInner:not([class*="h-["])::after {
  content: ""; position: absolute; inset: 1px; z-index: 0; pointer-events: none;
  background: var(--encom-panel2);
  clip-path: polygon(var(--encom-chamfer-in) 0, 100% 0, 100% calc(100% - var(--encom-chamfer-in)),
                     calc(100% - var(--encom-chamfer-in)) 100%, 0 100%, 0 var(--encom-chamfer-in));
}
.bg-sixth:not([class*="h-["]) > *,
.bg-newBgColorInnerInner:not([class*="h-["]) > * { position: relative; z-index: 1; }

/* 4. The panel header row. Postiz builds card heads as
      `bg-newBgColorInner px-[20px] py-[14px] border-b border-newBorder`; that bottom border is
      the Grid's .ph rule, so the row gets the .ph voice — Michroma, wide tracking, uppercase. */
[class*="bg-newBgColorInner"][class*="px-[20px]"][class*="py-[14px]"][class*="border-b"] {
  font-family: "Michroma", "Futura", sans-serif !important;
  letter-spacing: 0.22em; text-transform: uppercase; font-size: 10px !important;
  color: var(--encom-mcp2) !important;
  border-bottom-color: var(--encom-frame-dim) !important;
}

/* 5. Postiz purple that never went through a token (bg-[#612BD3] ×27 and friends) */
[class*="bg-[#612BD3]"], [class*="bg-[#612bd3]"], [class*="bg-primary"], [class*="bg-fifth"] {
  background-color: rgba(var(--encom-glow-rgb), 0.12) !important;
  box-shadow: inset 0 0 0 1px var(--encom-frame);
  color: var(--encom-mcp2) !important;
}
/* Pure white text is off-palette — the Grid's brightest ink is #e6f7f8 (text-white ×73) */
[class*="text-white"] { color: var(--encom-text) !important; }
[class*="text-gray-400"], [class*="text-customColor18"] { color: var(--encom-muted) !important; }
/* reds stay red: --alert is theme-invariant in grid.css */
[class*="text-red-4"], [class*="bg-red-5"] { color: var(--encom-alert) !important; }

/* 6. Tables in the Grid's voice: header letterspaced and quiet, rules in the frame colour */
/* Only real table heads take the Grid's header voice. `bg-newTableHeader` is NOT a table
   class — Postiz reuses it for the calendar's day-of-week cells, which live in a fixed
   `grid-cols-7`. Michroma at 0.18em tracking made "Monday" wider than its column and the
   seven day names collided into each other. Colour only for that class; type for thead/th. */
thead, thead th {
  font-family: "Michroma", "Futura", sans-serif; letter-spacing: 0.18em;
  text-transform: uppercase; font-size: 9px; color: var(--encom-muted) !important;
}
/* box-shadow, not border-bottom: these cells sit in a fixed grid-rows-[62px_auto] and an extra
   border-box pixel shifts the whole calendar. A shadow draws the Grid's column rule for free. */
[class*="bg-newTableHeader"] { background: var(--encom-panel2) !important;
  box-shadow: inset 0 -1px 0 var(--encom-frame-dim); }
td, th { border-color: var(--encom-frame-dim) !important; }

/* 7. Icon buttons (bg-newColColor, 30×30) read as Grid chips: square, framed, lit on hover */
.bg-newColColor, [class*="bg-btnSimple"] {
  background: var(--encom-panel2) !important;
  box-shadow: inset 0 0 0 1px var(--encom-frame-dim);
}
.bg-newColColor:hover, [class*="bg-btnSimple"]:hover {
  box-shadow: inset 0 0 0 1px var(--encom-frame), 0 0 10px rgba(var(--encom-glow-rgb), 0.2);
}

/* 8. Menus, modals and popovers: framed and lit rather than shadowed */
[class*="menu-shadow"], [role="dialog"], [class*="modal"] {
  background: var(--encom-panel) !important;
  box-shadow: 0 0 0 1px var(--encom-frame), 0 0 30px rgba(0, 0, 0, 0.7),
              0 0 20px rgba(var(--encom-glow-rgb), 0.08) !important;
}

/* 9. Scrollbars: thin, frame-coloured, square */
* { scrollbar-width: thin; scrollbar-color: var(--encom-frame-dim) transparent; }
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--encom-frame-dim); border-radius: 0; }
::-webkit-scrollbar-thumb:hover { background: var(--encom-frame); }

/* 10. Nesting. Postiz builds a card as bg-newBgColorInner (shell) wrapping a header row and a
       body that are *also* bg-newBgColorInner. Chamfering each one draws three frames where the
       Grid draws one, so descendants stand down and let the outermost shell carry the frame.
       The header keeps its border-b, which is what the Grid's .ph rule is anyway. */
.bg-newBgColorInner .bg-newBgColorInner::before,
.bg-newBgColorInner .bg-newBgColorInner::after,
.bg-sixth .bg-newBgColorInner::before,
.bg-sixth .bg-newBgColorInner::after { content: none !important; }
.bg-newBgColorInner .bg-newBgColorInner:not([class*="h-["]):not([class~="fixed"]) { background-color: transparent !important; }

/* 11. Never re-typeset inside a grid. Postiz sizes grid columns to its own font metrics, so a
       wider face or added tracking overflows the cell — this is what broke the calendar's day
       row. Decoration is fine anywhere; type is not. */
[class*="grid-cols-"] *, [class*="grid-template-columns"] *, [class*="grid-rows-"] * {
  font-family: "Share Tech Mono", "Menlo", monospace !important;
  letter-spacing: normal !important;
  text-transform: none !important;
}

/* ═══ DENSITY — the half of the eDEX register that is not colour ════════════════════════════
   Measured against docs/prototypes/tower/index.html in master-control (the Grid prototype,
   wayfinder #19, "eDEX-red is the Grid's design"). Chamfer and palette were already right;
   what was missing is that eDEX is *dense* — small mono type, tight padding, no wasted space.
   Postiz ships a loose, large-type layout, so the register never read no matter the colours.

   Selectors use ~= (exact word in the class list), never *=. `[class*="p-[20px]"]` also matches
   `gap-[20px]`, which would have silently rewritten every gap in the app. */

body { font-size: 13px; line-height: 1.38; }

/* type scale down one step; the prototype's body is ~12px and its headers ~9-10px */
[class~="text-[24px]"] { font-size: 16px !important; }
[class~="text-[20px]"] { font-size: 14px !important; }
[class~="text-[16px]"] { font-size: 13px !important; }
[class~="text-[15px]"] { font-size: 12px !important; }
[class~="text-[14px]"] { font-size: 12px !important; }
[class~="text-[13px]"] { font-size: 11px !important; }
[class~="text-[12px]"] { font-size: 11px !important; }
[class~="text-[40px]"] { font-size: 24px !important; }

/* padding and gaps in. Postiz's p-[20px]/p-[24px] are roughly double the prototype's 10-12px. */
[class~="p-[24px]"]  { padding: 12px !important; }
[class~="p-[20px]"]  { padding: 11px !important; }
[class~="p-[12px]"]  { padding: 8px !important; }
[class~="px-[20px]"] { padding-left: 12px !important; padding-right: 12px !important; }
[class~="px-[16px]"] { padding-left: 10px !important; padding-right: 10px !important; }
[class~="py-[14px]"] { padding-top: 7px !important; padding-bottom: 7px !important; }
[class~="gap-[24px]"] { gap: 10px !important; }
[class~="gap-[20px]"] { gap: 10px !important; }
[class~="gap-[16px]"] { gap: 8px !important; }
[class~="gap-[15px]"] { gap: 8px !important; }
[class~="gap-[12px]"] { gap: 8px !important; }

/* Panel titles get the prototype's header: small, tracked, uppercase, and a rule running to the
   panel edge — CHRONO, USAGE WINDOWS, SECTORS · THE GRID, I/O TOWER. This is the single most
   recognisable piece of eDEX chrome and Postiz had nothing like it.
   Flex containers only: a grid cannot absorb the extra tracking (that is what broke the
   calendar's day row), and rule 11 already pins type inside grids. */
.bg-newBgColorInner > [class~="text-[20px]"],
.bg-sixth > [class~="text-[20px]"] {
  font-family: "Michroma", "Futura", sans-serif !important;
  font-size: 10px !important; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--encom-mcp2) !important;
  display: flex; align-items: center; gap: 10px; margin-bottom: 2px;
}
.bg-newBgColorInner > [class~="text-[20px]"]::after,
.bg-sixth > [class~="text-[20px]"]::after {
  content: ""; flex: 1; min-width: 12px; height: 1px; background: var(--encom-frame-dim);
}

/* Controls shrink with everything else, or the density reads as inconsistent */
[class~="h-[44px]"] { height: 32px !important; }
[class~="h-[42px]"] { height: 32px !important; }
[class~="h-[38px]"] { height: 30px !important; }
input, textarea, select { font-size: 12px !important; }

/* ═══ THE I/O TOWER — the left rail, the focused state, and the two marks ════════════════════
   Everything below came out of looking at the skinned app logged in (the auth page is the only
   screen an unauthenticated session can see, and it has no rail, no menus and no focused state). */

/* 1. The focused state was painting a *bright* box. `--new-boxFocused` is the eDEX ink colour
      (#aacfd1) and Postiz uses it as a BACKGROUND under `text-textItemFocused` (#e6f7f8) — pale
      ink on a pale box, so the active rail item and the Day/Week/Month pills were near-unreadable
      light rectangles in an otherwise black app. The Grid marks the selected thing by lighting
      its frame, not by inverting it. The token itself stays bright, because two components use it
      as `border-boxFocused`; only the background utility is remapped, and `~=` keeps the
      `hover:bg-boxFocused` variant out of it (a `*=` match would pin every hover state on). */
[class~="bg-boxFocused"] {
  background-color: rgba(var(--encom-glow-rgb), 0.13) !important;
  box-shadow: inset 0 0 0 1px var(--encom-frame);
}
[class~="hover:bg-boxFocused"]:hover {
  background-color: rgba(var(--encom-glow-rgb), 0.09) !important;
  box-shadow: inset 0 0 0 1px var(--encom-frame-dim);
}

/* 2. Centre the rail. Postiz gives the primary group `flex-1` with no justification, so six items
      pack against the top of a full-height rail and the seventh (Settings) is pinned to the
      bottom — on a 900px window that leaves ~250px of dead rail in the middle. */
#left-menu > div > div:first-of-type { justify-content: center; }

/* 3. Line the items up with each other. Each item is `h-[54px] py-[8px] flex-col justify-center`,
      which centres the icon+label pair — but only as well as the icons are uniform, and Postiz's
      run 19-23px tall at six different aspect ratios, so every label sat a pixel or two off its
      neighbour and the tallest pair filled the well edge to edge. A fixed 20px icon box gives the
      whole rail one baseline: 20 + 4 gap + 11 label = 35px inside the 54px well (the 2026-08-25
      live capture, docs/channels/postiz-rail-dom.md, verified this VERTICAL claim holds: the 35px
      stack sits dead-centred, 9.5px above and below, ink centres == box centres on all seven).
      scripts/check-align.py keeps it so — do not change these heights without re-running it. */
#left-menu a > div:first-child, #left-menu button > div:first-child {
  height: 20px; display: flex; align-items: center; justify-content: center;
}
#left-menu a svg, #left-menu button svg { height: 20px; width: auto; }
#left-menu a > div:last-child, #left-menu button > div:last-child { line-height: 1.1; }

/* 3b. Centre the rail HORIZONTALLY — the defect the same capture actually named. Postiz renders
      `#left-menu` as `fixed w-[64px] start-[17px]` over the 80px rail card: 17px of left inset
      against −1px of right, and the items' min-content width is 70.5px (the nowrap "Integrations"
      label at 10px/600 refuses to shrink), so every item spanned [25,95.5] over a card [8,88] —
      icon centres 12.25px right of the card's centre, the widest label crossing the right rail
      line. The menu's fixed containing block starts at the card's left edge (start-[17px] rendered
      at x = card.left + 17), so `inset-inline-start: 0` pins the menu to the card and `width: 80px`
      makes the two boxes coincide: items go w-full = 80px, the 70.5px min-content fits, and every
      icon centre lands on the card's centre line (48).
      LABEL STRATEGY — keep "Integrations" at 10px on one line: at 80px it fits (58.5px text + 12px
      item padding = 70.5 ≤ 80), so nothing shrinks, wraps or truncates today; smaller type or a
      forced wrap would cost legibility to solve a problem the wider menu already solved. The
      `overflow-wrap: anywhere` on the label is the guard for a FUTURE longer label: it wraps to a
      second line inside the card (20 icon + 4 gap + 2×11px lines = 46 ≤ the 54px well) instead of
      re-crossing the rail line, and it collapses the min-content floor that caused the overflow. */
#left-menu { inset-inline-start: 0 !important; width: 80px !important; }
#left-menu a > div:last-child, #left-menu button > div:last-child {
  max-width: 100%; overflow-wrap: anywhere;
}

/* 4. The compliance footer is `position: fixed`, so it was lying on top of the bottom of every
      page — including the rail's Settings item, which was half behind it. Reserve its height
      instead of overlapping it. The rail is `fixed h-full`, so it needs its own reservation. */
[class*="min-h-screen"] { padding-bottom: calc(var(--encom-footer-height, 96px) + 8px) !important; }
#left-menu { padding-bottom: calc(var(--encom-footer-height, 96px) + 8px); }

/* 5. The mark, and the wordmark on the agent. The rail slot gets the closed ENCOM disc E; the
      agent screen is the one place with room for the name, so its `Agent` title becomes the
      wordmark itself. `.trz` is the agents-only wrapper (agent.tsx), and it is a cousin of the
      title rather than an ancestor, so `:has()` on their common shell is what identifies the
      screen — Next gives the route no class of its own. */
[class*="bg-newBgLineColor"]:has(.trz) [class~="text-[24px]"] > h1 {
  font-size: 0 !important;
  width: 150px; height: 34px;
  background: url(/encom/wordmark.svg) left center / contain no-repeat;
  filter: drop-shadow(0 0 6px rgba(var(--encom-glow-rgb), 0.4));
}

/* 6. Select Channels, in the Grid's voice. Postiz draws the picker as bare avatars and says
      "not selected" by dropping the whole row to opacity-20 — on navy that is indistinguishable
      from disabled, and it was the least Tron thing on the screen. The Grid states selection with
      the frame: every channel stays a legible chip, the chosen ones are lit and full-colour. */
.trz [class*="group/profile"] {
  padding: 6px 8px;
  box-shadow: inset 0 0 0 1px var(--encom-frame-dim);
  background: linear-gradient(90deg, rgba(var(--encom-glow-rgb), 0.05), transparent 70%);
  transition: box-shadow .15s ease, background .15s ease;
}
.trz [class*="opacity-20"] { opacity: 0.55 !important; }
.trz [class*="group/profile"] img {
  filter: grayscale(1) contrast(1.05) brightness(0.85);
  box-shadow: 0 0 0 1px var(--encom-frame-dim);
  transition: filter .15s ease;
}
.trz [class*="group/profile"]:not([class*="opacity-20"]) {
  background: rgba(var(--encom-glow-rgb), 0.10);
  box-shadow: inset 3px 0 0 0 var(--encom-mcp), inset 0 0 0 1px var(--encom-frame),
              0 0 14px rgba(var(--encom-glow-rgb), 0.18);
  color: var(--encom-mcp2);
}
.trz [class*="group/profile"]:not([class*="opacity-20"]) img { filter: none; }
.trz [class*="group/profile"]:hover { box-shadow: inset 0 0 0 1px var(--encom-frame); }
/* its header gets the panel-title voice; the h2 is nested, so the .ph rules above never reached it */
.trz h2 {
  font-size: 11px !important; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--encom-mcp2); display: flex; align-items: center; gap: 10px;
}
.trz h2::after { content: ""; flex: 1; min-width: 12px; height: 1px; background: var(--encom-frame-dim); }

/* 7. The same act in the composer: "check the circles above" is the other channel picker
      (picks.socials.component). Circles become framed Grid chips, and the selected one is lit
      rather than outlined in Postiz violet. */
[class*="border-[2px]"][class*="rounded-full"][class*="bg-fifth"] {
  border-radius: 0 !important;          /* rule 1 spares rounded-full for avatars; here it is the chip */
  border-color: var(--encom-frame) !important;
  background: var(--encom-panel2) !important;
}
[class*="border-[2px]"][class*="rounded-full"][class*="bg-fifth"] img { border-radius: 0 !important; }
[class*="border-[2px]"][class*="rounded-full"][class*="border-[#622FF6]"] {
  border-color: var(--encom-mcp) !important;
  box-shadow: 0 0 0 1px rgba(var(--encom-glow-rgb), 0.35), 0 0 14px rgba(var(--encom-glow-rgb), 0.35);
}

/* YouTube badges: the official padded PNG is served at Postiz's existing URL.
   40px canvas height gives 21.544px visible artwork (579 / 1075 of the canvas).
   Put it beside the avatar on a solid background; absolute overlays would cover
   the avatar or place other artwork inside the logo's required clear space. */
img:is([src$="/icons/platforms/youtube.svg"], [src$="/icons/platforms/youtube.png"]) {
  position: static !important;
  width: auto !important; min-width: 0 !important; max-width: none !important;
  height: 40px !important; min-height: 40px !important; max-height: none !important;
  flex: none !important; object-fit: contain; aspect-ratio: auto;
  border: 0 !important; border-radius: 0 !important;
  clip-path: none !important; filter: none !important;
  box-shadow: none !important; opacity: 1 !important;
  background: var(--encom-bg);
}
/* The composer grays the whole chip when unselected. Move that effect to the
   avatar only, leaving the YouTube colors intact in both selection states. */
.relative:has(> img:is([src$="/icons/platforms/youtube.svg"], [src$="/icons/platforms/youtube.png"])) {
  filter: none !important; gap: 4px;
}
.relative.grayscale:has(> img:is([src$="/icons/platforms/youtube.svg"], [src$="/icons/platforms/youtube.png"])) > img[alt="youtube"] {
  filter: grayscale(1);
}
/* The Agent picker also dims the entire unselected row. Keep its mark opaque;
   dim only the avatar and label. The existing frame still indicates selection. */
.trz [class*="group/profile"][class*="opacity-20"]:has(img[src$="/icons/platforms/youtube.png"]) {
  opacity: 1 !important;
}
.trz [class*="group/profile"][class*="opacity-20"]:has(img[src$="/icons/platforms/youtube.png"]) > div:last-child,
.trz [class*="group/profile"][class*="opacity-20"] img[alt="youtube"]:not([src$="/icons/platforms/youtube.png"]) {
  opacity: 0.55;
}
/* Selected-channel tabs otherwise force avatar + badge into a 40px square. */
.border.cursor-pointer:has(> [data-tooltip-id="tooltip"] > img:is([src$="/icons/platforms/youtube.svg"], [src$="/icons/platforms/youtube.png"])) {
  width: auto !important; height: 44px !important; flex-shrink: 0;
}
[data-tooltip-id="tooltip"]:has(> img:is([src$="/icons/platforms/youtube.svg"], [src$="/icons/platforms/youtube.png"])) {
  width: auto !important; height: 40px !important; padding-inline: 2px;
}
/* The two-column composer can shrink below an avatar plus the official badge on phones. */
@media (max-width: 640px) {
  .border-e:has(#social-content) { min-width: 156px; }
}

/* 8. The last violet that no token reaches.
      - SVGLine (launches.component) is a 5×52 SVG whose gradient stops are literal #662FDA —
        it draws the bar beside the active Settings tab and the channel hover marker.
      - Spinner (loading.tsx) hard-codes #612bd3 on an INLINE style; an !important author rule
        still outranks an inline declaration, and the serialised colour identifies it (Chrome
        writes the shorthand back as `border-color: rgb(97, 43, 211) transparent transparent`,
        so matching the animation name or the hex literal would both miss).
      - The remaining arbitrary utilities that the earlier pass listed for text/border but not
        background. */
svg[viewBox="0 0 5 52"] stop { stop-color: var(--encom-mcp); }
[style*="rgb(97, 43, 211)"] { border-top-color: var(--encom-mcp) !important; }
[class*="bg-[#5520CB]"], [class*="bg-[#FC69FF]"], [class*="bg-[#D82D7E]"] {
  background-color: #16454c !important; box-shadow: inset 0 0 0 1px var(--encom-frame);
}
[class*="from-[#7c3aff]"] { --tw-gradient-from: #16454c !important; }
[class*="to-[#9d6eff]"] { --tw-gradient-to: #2a6f78 !important; }

/* 9. The on/off slider (react-shared-libraries/form/slider) was a white puck on a violet track —
      the only pill left in an app with no rounded corners. Square track, lit knob. */
[class~="w-[57px]"][class~="h-[34px]"] {
  background: var(--encom-panel2) !important; border-color: var(--encom-frame-dim) !important;
}
[class~="w-[57px]"][class~="h-[34px]"] [class*="bg-customColor5"] {
  background-color: var(--encom-mcp) !important; border-radius: 0 !important;
  box-shadow: 0 0 10px rgba(var(--encom-glow-rgb), 0.45);
}
[class*="bg-customColor4"] { background-color: rgba(var(--encom-glow-rgb), 0.16) !important; }

/* 10. Media library tiles. Postiz crops every asset into a square with object-cover, which
      beheads the 16:9 episode thumbnails (the NO-FI wordmark loses its N) and zooms video
      posters arbitrarily. Letterbox instead: the full frame on a panel ground. `.withp3` is
      the media grid's own wrapper (media.component) and nothing else uses it, so the rule
      cannot reach avatars or calendar previews. Video tiles still open on their first frame —
      the episodes fade in from black, so a dark tile there is the file, not a bug. */
.withp3 img, .withp3 video {
  object-fit: contain !important;
  background: var(--encom-panel2);
}

/* 11. Media tiles: kind badges. skin.js snapshots every grid video's artwork frame and tags
      the cell data-encom-kind="track" (duration < 8 min — the wrapped No-Fi tracks) or
      "episode" (the long-form videos), because the hashed filenames give the DOM no other
      signal and Nick can't tell which content is which type. A corner chip names the kind;
      until the snapshot lands, a centred ▶ marks the tile as footage-still-loading. Plain
      images (the upload thumbnails) get no chip — they are what they look like. */
.withp3 [class*="float-left"] { position: relative; }
.withp3 [class*="float-left"]:has(video):not([data-encom-kind])::after {
  content: "▶";
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 24px;
  color: rgba(var(--encom-glow-rgb), 0.8);
  text-shadow: 0 0 10px rgba(var(--encom-glow-rgb), 0.6);
  pointer-events: none;
}
.withp3 [data-encom-kind]::after {
  position: absolute; top: 8px; left: 8px;
  padding: 2px 7px;
  font-size: 10px; letter-spacing: 0.08em;
  color: var(--encom-panel);
  background: rgba(var(--encom-glow-rgb), 0.9);
  box-shadow: 0 0 8px rgba(var(--encom-glow-rgb), 0.5);
  pointer-events: none;
}
.withp3 [data-encom-kind="track"]::after   { content: "♪ TRACK"; }
.withp3 [data-encom-kind="episode"]::after { content: "▶ EPISODE"; }

/* 12. Fixed overlays that §2 now leaves alone still need the Grid look. The ⋮ dropdown
      (shadow-menu) is the one Postiz ships today: solid panel, lit frame, square corners. */
[class*="shadow-menu"][class~="fixed"] {
  background-color: var(--encom-panel2) !important;
  border: 1px solid var(--encom-frame) !important;
  border-radius: 0 !important;
  width: max-content !important;
  max-width: none !important;
  overflow: visible;
}
/* The menu's z-[100] is trapped in its panel's stacking context (§2 gives every panel child
   z-index:1), and the calendar subtree paints later — so hour labels printed straight over
   the open menu. While a menu is open, lift the whole ancestor chain that contains it; the
   selector matches nothing the rest of the time. */
div:has(> [class*="shadow-menu"][class~="fixed"]),
div:has([class*="shadow-menu"][class~="fixed"]) {
  z-index: 70;
}
[class*="shadow-menu"] [class*="py-[8px]"]:hover {
  background: rgba(var(--encom-glow-rgb), 0.12);
}

/* 13. The tower. Nick wants the Encom tower mark at the top-left of the app's menu bar; the
      bar is the only `h-[80px] bg-newBgColorInner` strip, so its ::before (unused — the h-[
      variant takes the §2 fixed-height styling, which draws no pseudo layers) carries the
      glyph. tower.svg is drawn in the skin's own register (monoline + thin contour), not
      taken from any franchise art. */
[class*="h-[80px]"][class*="bg-newBgColorInner"][class*="items-center"]::before {
  content: "";
  flex: none;
  width: 38px; height: 56px;
  margin-right: 16px;
  background: url("/encom/tower.svg") center / contain no-repeat;
  filter: drop-shadow(0 0 6px rgba(var(--encom-glow-rgb), 0.35));
}

/* 14. Ink that was written for surfaces that no longer exist. Postiz pairs these text classes
      with light grounds (white buttons, pale chips); §"no light surfaces" darkened every
      ground, so anything set in them became black-on-black — invisible until a hover state
      happens to repaint it (Nick, 2026-08-25). Audit method: walk every .text-* rule in the
      loaded stylesheets and flag colours with luminance < 0.06; these nine are the complete
      list for v2.22.1. All become theme ink; text-forth (the dark teal also used as a button
      ground) brightens to the mark colour instead so it still reads as an accent. */
.text-black, .text-primary, .text-customColor16, .text-customColor40,
.text-newBgColor, .text-newColColor, .text-bgLinkedin,
[class*="text-[#0E0E0E]"] {
  color: var(--encom-text) !important;
}
.text-forth { color: var(--encom-mcp) !important; }
