/*
Theme Name: PennySlice
Theme URI: https://pennyslice.ai
Description: PennySlice brand theme for the blog. A child of Twenty Twenty-Five — it inherits every template and overrides only the design tokens, so WordPress core theme updates continue to apply.
Author: Zednest Tech
Template: twentytwentyfive
Version: 1.1.0
License: Proprietary
Text Domain: pennyslice
*/

/*
 * Colours, fonts, spacing and layout live in theme.json — that is what feeds
 * the block editor, so an author picking "Brand teal" gets the same #14B8A6
 * the app uses. This file covers what theme.json cannot express: the dark
 * scheme, the shared header and footer, and reading typography.
 */

/* ── Dark mode ───────────────────────────────────────────────────────────────
 *
 * Keyed off `html.dark`, NOT `prefers-color-scheme`, because that is what the
 * marketing site uses. Its ThemeProvider resolves the preference — which may be
 * an explicit light/dark choice rather than the OS setting — and toggles that
 * one class on <html>. The blog reads the same cookie and applies the same
 * class (see pennyslice_theme_bootstrap in functions.php), so a reader who
 * picked dark on pennyslice.ai stays in dark here even if their OS is light.
 *
 * Values are the dark-side tokens from packages/ui/src/styles/tokens.css and
 * website/src/styles/tokens.css, in the same order as the light values in
 * theme.json so the two can be diffed by eye.
 */
html.dark {
  --wp--preset--color--base: #080e1a;
  --wp--preset--color--surface: #0f172a;
  --wp--preset--color--card: #1e293b;
  --wp--preset--color--contrast: #f1f5f9;
  --wp--preset--color--contrast-2: #e2e8f0;
  --wp--preset--color--contrast-3: #cbd5e1;
  --wp--preset--color--muted: #94a3b8;
  --wp--preset--color--divider: rgba(255, 255, 255, 0.05);
  --wp--preset--color--card-border: rgba(255, 255, 255, 0.05);

  /* Full-saturation teal vibrates against near-black. The marketing site
     lightens to the accent shade in dark mode; matching keeps links legible. */
  --wp--preset--color--brand: #2dd4bf;

  --ps-nav-bg: rgba(8, 14, 26, 0.78);
  --ps-nav-border: rgba(255, 255, 255, 0.06);
  --ps-footer-bg: #070d18;
  --ps-footer-border: rgba(255, 255, 255, 0.05);
  --ps-footer-hover: #ffffff;
  --ps-social-bg: rgba(255, 255, 255, 0.03);
  --ps-social-border: rgba(255, 255, 255, 0.06);
  --ps-hover-bg: rgba(255, 255, 255, 0.04);
  --ps-brand-300: #5EEAD4;
  --ps-brand-400: #2DD4BF;
  --ps-text-500: #64748B;
}

:root {
  --ps-nav-bg: rgba(255, 255, 255, 0.88);
  --ps-nav-border: rgba(0, 0, 0, 0.06);
  --ps-footer-bg: #ebeeed;
  --ps-footer-border: rgba(0, 0, 0, 0.06);
  --ps-footer-hover: #1c1917;
  --ps-social-bg: rgba(0, 0, 0, 0.04);
  --ps-social-border: rgba(0, 0, 0, 0.06);
  --ps-hover-bg: rgba(0, 0, 0, 0.03);
  --ps-brand-300: #0F766E;
  --ps-brand-400: #0D9488;
  --ps-text-500: #A8A29E;
  --ps-max: 1200px;
}

html.dark img,
html.dark video {
  /* Stops bright media burning out against the dark surface — the same
     treatment the marketing site applies to its screenshots. */
  filter: brightness(0.92);
}

/* The marketing site sets these on body; Twenty Twenty-Five does not, and the
   difference is visible as slightly heavier, blurrier text side by side. */
body {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* The toggle shows the scheme you would switch TO, matching the marketing
   site's button. */
.ps-icon-sun { display: none; }
html.dark .ps-icon-sun { display: block; }
html.dark .ps-icon-moon { display: none; }

/* ── Header ──────────────────────────────────────────────────────────────────
 *
 * Mirrors .nav / .nav-inner / .nav-links / .nav-right / .btn-demo in
 * website/src/styles/tokens.css. Values are copied rather than shared because
 * the blog cannot import the React app's stylesheet — keep them in step by
 * diffing against that file, which is the original.
 *
 * Fixed rather than sticky, matching the app: sticky inside a flex column
 * janks under the high-frequency scroll events a Magic Mouse emits.
 */
.ps-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  transition: background 200ms, border-color 200ms, backdrop-filter 200ms;
}

/* Transparent over the page until scrolled, like the marketing site. The
   class is toggled by the scroll listener in functions.php. */
.ps-nav.scrolled {
  background: var(--ps-nav-bg);
  border-bottom: 1px solid var(--ps-nav-border);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
}

.ps-nav-inner {
  max-width: var(--ps-max);
  margin: 0 auto;
  padding: 14px clamp(16px, 4vw, 32px);
  display: flex;
  align-items: center;
  gap: 20px;
}

.ps-nav-logo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
}

.ps-nav-logo-text {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--wp--preset--color--contrast);
}

.ps-nav-logo-accent { color: var(--ps-brand-400); }

/* Left-aligned beside the logo, not pushed to the right edge. */
.ps-nav-links {
  display: flex;
  gap: 4px;
  margin-left: 28px;
}

.ps-nav-links a {
  font-size: 14px;
  font-weight: 500;
  color: var(--wp--preset--color--contrast-3);
  padding: 8px 14px;
  border-radius: 8px;
  text-decoration: none;
  transition: color 160ms, background 160ms;
}

.ps-nav-links a:hover {
  color: var(--wp--preset--color--contrast);
  background: var(--ps-hover-bg);
}

.ps-nav-spacer { flex: 1; }

.ps-nav-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Also the theme toggle: a bare icon with no border or background, matching
   the marketing site's ThemeSwitch, which reuses this same class. */
.ps-nav-signin {
  font-size: 14px;
  font-weight: 500;
  color: var(--wp--preset--color--contrast-3);
  padding: 8px 14px;
  background: none;
  border: none;
  cursor: pointer;
  text-decoration: none;
  transition: color 160ms;
}

.ps-nav-signin:hover { color: var(--wp--preset--color--contrast); }

button.ps-theme-toggle {
  display: inline-flex;
  align-items: center;
  padding: 8px 10px;
}

/* A soft outlined pill, not a solid fill. */
.ps-btn-demo {
  display: inline-flex;
  align-items: center;
  font-size: 14px;
  font-weight: 600;
  color: var(--ps-brand-300);
  padding: 9px 20px;
  border-radius: 999px;
  border: 1px solid rgba(45, 212, 191, 0.28);
  background: rgba(45, 212, 191, 0.08);
  text-decoration: none;
  transition: background 160ms, border-color 160ms, color 160ms;
}

.ps-btn-demo:hover {
  background: rgba(45, 212, 191, 0.16);
  border-color: rgba(45, 212, 191, 0.45);
  color: var(--wp--preset--color--contrast);
}

/* The fixed header is out of flow, so the page needs its height back. */
body { padding-block-start: 64px; }

.ps-nav-theme-mobile { display: none; }

@media (max-width: 768px) {
  .ps-nav-links,
  .ps-nav-right { display: none; }
  .ps-nav-theme-mobile { display: inline-flex; align-items: center; }
}

/* ── Footer ──────────────────────────────────────────────────────────────────
 *
 * Mirrors .site-footer / .footer-* in website/src/styles/tokens.css, including
 * its 640px overrides. Values are copied rather than shared because the blog
 * cannot import the React app's stylesheet — diff against that file, which is
 * the original.
 */
.ps-footer {
  background: var(--ps-footer-bg);
  border-top: 1px solid var(--ps-footer-border);
  padding-top: 64px;
  padding-bottom: 28px;
}

.ps-footer-inner {
  max-width: var(--ps-max);
  margin: 0 auto;
  padding: 0 clamp(16px, 4vw, 32px);
}

.ps-footer-grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(4, 1fr);
  gap: 36px;
  padding-bottom: 44px;
  border-bottom: 1px solid var(--ps-footer-border);
}

@media (max-width: 860px) {
  .ps-footer-grid {
    grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
  }
}

.ps-footer-col-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--wp--preset--color--contrast-3);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 16px;
}

.ps-footer-col-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.ps-footer-col-list a {
  font-size: 14px;
  color: var(--wp--preset--color--muted);
  text-decoration: none;
  transition: color 160ms;
}

.ps-footer-col-list a:hover { color: var(--ps-footer-hover); }

.ps-footer-tagline {
  font-size: 11px;
  color: var(--ps-brand-400);
  margin-top: 14px;
  letter-spacing: 0.18em;
  font-weight: 600;
  text-transform: uppercase;
}

.ps-footer-description {
  font-size: 13.5px;
  color: var(--ps-text-500);
  margin: 12px 0 0;
  line-height: 1.55;
  max-width: 280px;
}

.ps-footer-social {
  display: flex;
  gap: 10px;
  margin-top: 20px;
}

.ps-footer-social a {
  width: 34px;
  height: 34px;
  border-radius: 8px;
  background: var(--ps-social-bg);
  border: 1px solid var(--ps-social-border);
  display: grid;
  place-items: center;
  color: var(--wp--preset--color--muted);
  transition: color 160ms, border-color 160ms;
}

.ps-footer-social a:hover {
  color: var(--ps-brand-400);
  border-color: rgba(45, 212, 191, 0.30);
}

.ps-footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 24px;
  flex-wrap: wrap;
  gap: 8px;
}

.ps-footer-copyright {
  font-size: 12.5px;
  color: var(--ps-text-500);
}

.ps-footer-version {
  font-size: 12.5px;
  color: var(--ps-text-500);
  font-family: var(--wp--preset--font-family--mono);
}

@media (max-width: 640px) {
  .ps-footer { padding-top: 36px; padding-bottom: 20px; }
  .ps-footer-grid { gap: 20px; padding-bottom: 28px; }
  .ps-footer-col-title { font-size: 11px; margin-bottom: 10px; }
  .ps-footer-col-list a { font-size: 13px; }
  .ps-footer-description { font-size: 12.5px; }
  .ps-footer-tagline { font-size: 10px; margin-top: 10px; }
}

/* ── Blog index header ──────────────────────────────────────────────────────
 * Mirrors the marketing site's .page-hero rhythm: a tight display title with a
 * muted lead paragraph under it.
 */
.ps-page-header {
  margin-block: 3.5rem 3rem;
}

.ps-page-title {
  margin: 0;
  font-size: var(--wp--preset--font-size--xx-large);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--wp--preset--color--contrast);
}

.ps-page-subtitle {
  margin: 14px 0 0;
  max-width: 46ch;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--wp--preset--color--muted);
}

@media (max-width: 640px) {
  .ps-page-header { margin-block: 2.25rem 2rem; }
  .ps-page-subtitle { font-size: 1rem; }
}

/* ── Post list (blog index) ─────────────────────────────────────────────────
 * A list of entries to choose from, not the articles themselves.
 */
.ps-post-card {
  padding-block: 2rem;
  border-bottom: 1px solid var(--wp--preset--color--divider);
}

.ps-post-card:first-child { padding-block-start: 0; }
.ps-post-card:last-child { border-bottom: none; }

.ps-post-thumb {
  margin-block-end: 1.25rem;
  border-radius: 12px;
  overflow: hidden;
}

/* A featured image is never cropped. It fills the column and keeps its own
   proportions, whatever they are.

   Hero cards are generated at 1200x630 with the headline set against the left
   edge, so any imposed ratio crops to fill, and a centred crop eats the outer
   edges first: the index shipped pinned to 3/2 and rendered "ow to export
   transactions" under a wordmark sliced in half.

   `height: auto` rather than a declared ratio, so this holds for a hand-uploaded
   image too — pinning 1200/630 would fix today's heroes and crop anything else.
   No layout shift either way: WordPress emits width and height attributes, from
   which the browser derives the ratio and reserves the space before load.

   `object-fit` is reset because the block emits `object-fit:cover` inline, which
   would otherwise crop the moment anything constrained the height. It must also
   stay off the block's `aspectRatio` attribute — that emits an inline style,
   which beats this rule. A contract test holds both. */
.ps-post-thumb img,
.ps-article-hero img {
  width: 100%;
  height: auto;
  display: block;
  object-fit: fill;
}

.ps-post-title {
  margin: 0;
  font-size: clamp(1.375rem, 1.2rem + 0.8vw, 1.75rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
}

.ps-post-title a {
  color: var(--wp--preset--color--contrast);
  text-decoration: none;
  transition: color 160ms;
}

.ps-post-title a:hover { color: var(--wp--preset--color--brand); }

.ps-post-date {
  margin-block-start: 8px;
  font-size: 13px;
  color: var(--ps-text-500);
}

.ps-post-excerpt {
  margin-block-start: 12px;
  font-size: 1rem;
  line-height: 1.65;
  color: var(--wp--preset--color--contrast-3);
}

.ps-post-excerpt .wp-block-post-excerpt__more-text {
  margin-block-start: 10px;
}

.ps-post-excerpt .wp-block-post-excerpt__more-link {
  font-size: 14px;
  font-weight: 600;
  color: var(--wp--preset--color--brand);
  text-decoration: none;
}

.ps-post-excerpt .wp-block-post-excerpt__more-link:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.ps-pagination {
  margin-block-start: 2.5rem;
  padding-block-start: 1.5rem;
  border-top: 1px solid var(--wp--preset--color--divider);
  font-size: 14px;
}

.ps-pagination a { color: var(--wp--preset--color--brand); text-decoration: none; }
.ps-pagination a:hover { text-decoration: underline; }

/* ── Single article ─────────────────────────────────────────────────────── */

.ps-single { margin-block: 3.5rem 4rem; }

.ps-article-title {
  margin: 0;
  font-size: var(--wp--preset--font-size--xx-large);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.15;
}

.ps-article-meta {
  margin-block-start: 14px;
  gap: 0 10px;
  font-size: 13.5px;
  color: var(--ps-text-500);
}

/* Separators between date / author / category, without markup for them. */
.ps-article-meta > * + *::before {
  content: "·";
  margin-inline-end: 10px;
  color: var(--wp--preset--color--divider);
}

.ps-article-meta a {
  color: var(--ps-text-500);
  text-decoration: none;
}

.ps-article-meta a:hover { color: var(--wp--preset--color--brand); }

.ps-article-hero {
  margin-block: 2rem 0;
  border-radius: 12px;
  overflow: hidden;
}

.ps-article-tags:not(:empty) {
  display: block;
  margin-block-start: 2.5rem;
  font-size: 13.5px;
}

.ps-article-tags a {
  color: var(--wp--preset--color--brand);
  text-decoration: none;
}

/* ── More posts ─────────────────────────────────────────────────────────── */

.ps-more-posts {
  margin-block-start: 4rem;
  padding-block-start: 2rem;
  border-top: 1px solid var(--wp--preset--color--divider);
}

/* With no other posts the query renders nothing, leaving a bare heading over
   empty space. Hide the whole section rather than announce an empty list. */
.ps-more-posts:not(:has(.wp-block-post-template)) { display: none; }

.ps-more-posts-title {
  margin: 0 0 0.5rem;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--wp--preset--color--contrast-3);
}

.ps-more-post-row {
  padding-block: 1rem;
  border-bottom: 1px solid var(--wp--preset--color--divider);
  gap: 1rem;
}

.ps-more-post-row h3 {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.ps-more-post-row h3 a {
  color: var(--wp--preset--color--contrast);
  text-decoration: none;
  transition: color 160ms;
}

.ps-more-post-row h3 a:hover { color: var(--wp--preset--color--brand); }

.ps-more-post-row .wp-block-post-date {
  flex-shrink: 0;
  font-size: 13px;
  color: var(--ps-text-500);
}

/* ── Reading typography ──────────────────────────────────────────────────── */

.wp-block-post-content {
  font-size: 1.0625rem;
  line-height: 1.75;
}

.wp-block-post-content > * + * { margin-block-start: 1.5em; }

.wp-block-post-content h2 {
  margin-block-start: 2.5em;
  letter-spacing: -0.02em;
}

.wp-block-post-content h3 {
  margin-block-start: 2em;
  letter-spacing: -0.01em;
}

/* Brand underline rather than colour alone, which fails contrast against body
   text at this weight. */
.wp-block-post-content a:where(:not(.wp-element-button)) {
  color: var(--wp--preset--color--brand);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

.wp-block-post-content a:where(:not(.wp-element-button)):hover {
  text-decoration-thickness: 2px;
}

.wp-block-quote {
  border-inline-start: 3px solid var(--wp--preset--color--brand);
  padding-inline-start: 1.25em;
  font-style: normal;
  color: var(--wp--preset--color--contrast-3);
}

.wp-block-code,
.wp-block-preformatted {
  background: var(--wp--preset--color--surface);
  border: 1px solid var(--wp--preset--color--card-border);
  border-radius: 10px;
  padding: 1em 1.25em;
  font-size: 0.9375rem;
  overflow-x: auto;
}

/* Tables scroll inside their own container rather than forcing the page to. */
.wp-block-table { overflow-x: auto; }
.wp-block-table table { border-collapse: collapse; }

.wp-block-table th,
.wp-block-table td {
  border-bottom: 1px solid var(--wp--preset--color--divider);
  padding: 0.75em 1em;
  text-align: start;
}

.wp-block-table thead th {
  font-weight: 600;
  color: var(--wp--preset--color--contrast-2);
}

/* The site header and footer are the theme's own, so hide them inside the
   block editor — it renders template parts in place and would otherwise show
   a fixed-position nav over the editing canvas. */
.editor-styles-wrapper .ps-nav,
.editor-styles-wrapper .ps-footer { display: none; }

.editor-styles-wrapper body { padding-block-start: 0; }
