Stock & Crypto Capstone · Modern CSS · Incremental Deployment

Trading Dashboard, built week by week from a design system to a production-ready command center.

This showcase does not send a visitor straight into a finished dashboard with no context. It first documents the decisions, repository architecture, Week 02 design-token foundation, Week 03 semantic layout frame, Week 04 asymmetric content grid, Week 05 CSS architecture refactor, Week 06 container-aware components, Week 07 CSS-only motion and scroll timelines, AI co-piloting boundaries, and verification work that make the final application credible.

01Choose the Archetype
02Preserve Every Week
03Build Week 02 Tokens
04Frame Week 03 Layout
05Compose Week 04 Grid
06Refactor Week 05 CSS
07Adapt Week 06 Components
08Animate Week 07 Responsibly
09Co-Pilot & Verify
00

The visitor experience: see the engineering story before the dashboard

The online resume presents the project as a documented build, not only as a final screenshot.

Entry point

The Trading Dashboard tab opens this case study. A recruiter or instructor can understand why the project exists, how the interface strategy was chosen, and which modern CSS concepts were deliberately introduced before opening the current working milestone.

End-result path

The Project Hub always identifies the newest published week. During Week 07 it points to the High-Performance Micro-Interactions & CSS Scroll-Driven Animations milestone. As later milestones are added, only the hub's “latest build” link changes; the earlier weekly URLs remain intact for comparison.

Online Resume Build Story Project Hub Latest Week / Final Dashboard
01

Part 1: Choose the project archetype

All three blueprints are useful, but they organize information around different primary tasks.

Selected foundation

A: The Specialized Dashboard / Workspace

Best for: developer tools, financial trackers, game-stat planners, and personal productivity hubs.

Core structure: left navigation panel, main dynamic work area, context side-rail, and modular stat cards.

This is the correct primary archetype because stock and crypto users repeatedly monitor changing data, compare positions, switch analytical tools, and act from one workspace.

Supporting influence

B: The Modern Editorial / Tech Publication

Best for: gaming magazines, design digests, investigative blogs, recipes, and travel journals.

Core structure: dynamic header, asymmetric story grid, reading status bar, and fluid long-form typography.

This blueprint contributes the narrative layer needed for research notes, market explanations, weekly case-study writing, and readable analytical reports.

Supporting influence

C: The Curation & Discovery Portal

Best for: job boards, book or movie libraries, event directories, and searchable catalogs.

Core structure: filter sidebar, top search header, responsive card-grid gallery, and comparison widgets.

This blueprint contributes discoverability: watchlists, symbol search, asset filters, screeners, saved collections, and side-by-side comparisons.

Final decision

Archetype A is the foundation, with every listed structural element retained.

The finished Trading Dashboard combines the workspace behavior of Archetype A, the explanatory storytelling of Archetype B, and the search, filtering, gallery, and comparison behavior of Archetype C.

Workspace Core

Archetype A elements

  • Left navigation panel
  • Main dynamic work area
  • Context side-rail
  • Modular stat cards
Research Story

Archetype B elements

  • Dynamic header
  • Asymmetric story grid
  • Reading status bar
  • Fluid long-form typography
Discovery Tools

Archetype C elements

  • Filter sidebar
  • Top search header
  • Responsive card-grid gallery
  • Comparison widgets
02

Part 2: The multi-week deployment architecture

One repository and one domain preserve the complete evolution without overwriting earlier work.

recommended repository structure
my-capstone-project/
├── index.html          <-- Global landing page linking to every week
├── week02/
│   ├── index.html      <-- Week 02 Design System Token Page
│   └── styles.css      <-- Week 02 design tokens and presentation
├── week03/
│   ├── index.html      <-- Week 03 progress, created next week
│   └── styles.css
├── week04/
│   ├── index.html
│   └── styles.css
└── ...
Milestones remain permanent

Week 03 never replaces Week 02. Each directory is a frozen checkpoint that can be opened, reviewed, and compared later.

One repository, one domain

The root landing page becomes the stable public entry point while weekly subdirectories provide predictable URLs.

The latest build is easy to promote

Update one root link to the newest week. Recruiters can open the latest version while instructors can still inspect the full history.

Rollback and comparison stay simple

If a new milestone breaks, the previous published directory remains available while the newer work is repaired.

Create, launch, and publish the structure

  1. Create the repository root and the current week.

    Start with the global landing page and a dedicated Week 02 directory instead of placing every file in one folder.

  2. Make the root page the permanent directory.

    Add a visible link such as <a href="./week02/index.html">Open Week 02</a>. Later, add Week 03 beside it rather than replacing it.

  3. Keep each week's assets local to that week.

    Week 02's HTML loads ./styles.css. Future weeks may copy and intentionally evolve those tokens without silently changing old milestones.

  4. Launch locally from the repository root.

    Use a local static server so directory links behave the same way they will online.

  5. Commit the milestone before starting the next week.

    Use a clear commit message that identifies the completed deliverable and verification status.

  6. Publish the repository root through a static host.

    Set the host's publish directory to the repository root. The domain opens the global index.html; /week02/index.html opens the preserved milestone.

terminal workflow
mkdir -p my-capstone-project/week02
cd my-capstone-project

touch index.html week02/index.html week02/styles.css

# Preview the repository from its root.
python3 -m http.server 8000
# Open: http://localhost:8000/
# Week 02: http://localhost:8000/week02/index.html

# Preserve the milestone in Git.
git init
git add .
git commit -m "Build Week 02 trading dashboard design tokens"
git branch -M main
git remote add origin <your-repository-url>
git push -u origin main
03

Part 3: The Week 02 technical blueprint

Week 02 creates the Design System Token Page that will power every later dashboard layout.

Recognize each subject by the problem it solves

Color roles, not random values

OKLCH tokens let the dashboard describe meaning: canvas, surface, text, brand, data accent, positive movement, and risk.

Type that scales without losing zoom

A mixed rem + vw preferred value reacts to viewport width while retaining a root-relative component for accessibility.

Rhythm that survives every panel

Spacing constants prevent the navigation, stat cards, charts, side-rails, and comparison widgets from developing unrelated padding systems.

A token page before a dashboard layout

Week 02 validates the visual language first. The dashboard's structural layout is intentionally deferred to later milestones.

Apply the Week 02 requirements step by step

  1. Inventory semantic roles.

    List the colors and sizes the dashboard will need by purpose: background, surface, primary text, muted text, brand action, chart accent, heading sizes, and spacing intervals.

  2. Declare the shared token names in :root.

    Components should consume stable names. The theme changes token values instead of requiring component-specific color overrides.

  3. Create explicit light and dark blocks.

    Use :root for the light palette and html[data-theme="dark"] for the dark palette. The sample text/background pairs below measure approximately 15.87:1 and 17.01:1 contrast respectively.

  4. Build the required fluid type variables.

    Define --size-base, --size-heading-md, and --size-heading-lg. The heading tokens use clamp(); the preferred expression mixes rem with vw.

  5. Create the relative spacing scale.

    Define --space-xs, --space-sm, --space-md, and --space-lg in rem so browser font-size preferences influence the overall rhythm.

  6. Build a visual token page, not the complete dashboard.

    Render labeled color swatches, typography specimens, and spacing bars inside /week02/. This makes every token inspectable before layout work begins.

  7. Verify the system in both themes and at 200% zoom.

    Confirm readable contrast, visible focus states, fluid heading growth, no clipped text, and no horizontal overflow.

week02/styles.css token foundation
:root {
  color-scheme: light;

  --color-primary: oklch(0.52 0.14 55);
  --color-secondary: oklch(0.48 0.09 205);
  --color-background: oklch(0.97 0.008 255);
  --color-surface: oklch(0.995 0.002 255);
  --color-text: oklch(0.22 0.025 255);
  --color-text-muted: oklch(0.45 0.025 255);

  --size-base: 1rem;
  --size-heading-md: clamp(1.35rem, 1.18rem + 0.75vw, 2rem);
  --size-heading-lg: clamp(1.75rem, 1.3099rem + 1.8779vw, 3rem);

  --space-xs: 0.5rem;
  --space-sm: 0.75rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
}

html[data-theme="dark"] {
  color-scheme: dark;

  --color-primary: oklch(0.72 0.16 55);
  --color-secondary: oklch(0.78 0.12 205);
  --color-background: oklch(0.15 0.02 255);
  --color-surface: oklch(0.20 0.02 255);
  --color-text: oklch(0.95 0.01 255);
  --color-text-muted: oklch(0.72 0.02 255);
}

Color tokens

Primaryoklch()
Secondaryoklch()
Surfaceoklch()
Textoklch()

Fluid typography tokens

Trading intelligence, scaled fluidly.

Market context remains readable from mobile to desktop.

Base text stays rooted in rem for user-controlled zoom and font preferences.

Spacing constants

--space-xs
--space-sm
--space-md
--space-lg
Fluid scale mathematics

From 1.75rem at 375px to 3rem at 1440px

  1. Convert the endpoints at a 16px root: 1.75rem = 28px and 3rem = 48px.
  2. Calculate the viewport range: 1440 - 375 = 1065px.
  3. Calculate the size range: 48 - 28 = 20px.
  4. Convert the slope to viewport units: (20 / 1065) × 100 = 1.8779vw.
  5. Calculate the intercept: 28 - (0.018779 × 375) = 20.9577px = 1.3099rem.

--size-heading-lg: clamp(1.75rem, 1.3099rem + 1.8779vw, 3rem);

04

Part 4: Co-piloting with AI

AI drafts tokens and explains the calculations; the developer retains control of the layout and the audit.

Allowed assistance

Ask AI for an OKLCH token block, a contrast rationale, a bounded fluid-sizing formula, and a mathematical explanation that can be independently checked.

Boundary

Do not ask AI to generate the Trading Dashboard layout. Navigation, card hierarchy, side-rails, chart placement, and responsive composition remain deliberate human design decisions.

Prompt 1 · Designing the palette
I am building Archetype A: a Specialized Dashboard for stock and crypto trading in OKLCH color space. I want a dark/light mode setup. Can you output a CSS :root block with color variables utilizing oklch()? The background and text colors must pass WCAG AA contrast guidelines. Please explain the math behind the Lightness (L) levels you chose for both light and dark mode to guarantee contrast.
Prompt 2 · Calculating fluid scales
I need a CSS custom property for a main title font size that scales fluidly. It should have a minimum size of 1.75rem at 375px viewport width, and a maximum size of 3rem at 1440px viewport width. Can you write the clamp() property using a mix of rem and vw, and break down exactly how the middle viewport-width expression is calculated?
Keep the output narrow

Request only the token block or formula being studied. Smaller outputs are easier to inspect and less likely to introduce unrelated layout decisions.

Check the explanation

Recalculate the slope, intercept, endpoints, and contrast with independent tools instead of accepting confident wording as proof.

Integrate selectively

Copy only the approved variables into week02/styles.css; rename them to match the project's semantic token system.

Record human decisions

Document why the palette, scale, and spacing fit the Trading Dashboard so the case study demonstrates judgment, not only generation.

05

Part 5: Verification and submission checklist

The milestone is complete only after the browser behavior and repository paths are manually confirmed.

  • Verification Test

    Press Ctrl + + or Cmd + + until the browser reaches 200% zoom. The typography must grow, wrap, and remain readable without clipping or horizontal scrolling.

  • Rewrite frozen formulas

    If a heading appears frozen because the preferred value uses pure vw, rewrite it so the middle expression mixes rem and vw.

  • No Overwriting Test

    Confirm the project root contains a global index.html and that its Week 02 link opens /week02/index.html directly.

  • Direct URL Test

    Paste the Week 02 URL into a new browser tab. It must load independently rather than relying on navigation state from the root page.

  • Theme Test

    Inspect every swatch and text sample in light and dark mode. Confirm the text/background pair remains visually distinct and at least 4.5:1.

  • Milestone Preservation Test

    Before Week 03 begins, commit Week 02 and verify that the next directory will be added beside it rather than on top of it.

00

Week 03: Semantic layout frame for the Trading Dashboard

Week 03 turns the Week 02 token system into a structural frame that can support stock and crypto analysis without pretending the final dashboard is finished.

Trading workspace standard

The foundation follows the proven trading-dashboard pattern: a left navigation/watchlist rail, a top control and search header, a main market workspace, and a right context drawer for selected-asset details, news, alerts, and risk notes.

All three archetypes stay active

Archetype A provides the dashboard shell. Archetype B appears inside the workspace through story and status regions. Archetype C appears through filters, search, responsive card galleries, and comparison widgets.

01

Part 1: Preserving your progress

Week 03 is added beside Week 02. It does not overwrite the design-token milestone.

  1. Copy the Week 02 foundation forward.

    Use Week 02's styles.css token system as the starting point for /week03/styles.css, then add only the new layout-frame rules required for this milestone.

  2. Keep the Week 02 URL stable.

    /trading-dashboard/week02/index.html remains the finished Design System Token Page and must continue to load independently.

  3. Create the Week 03 folder as the next checkpoint.

    /trading-dashboard/week03/index.html becomes the live Semantic Layout Frame while future weeks continue the same archive pattern.

02

Part 2: The Week 03 technical blueprint

Week 03 maps the physical skeleton of a real trading workspace using semantic HTML5 landmarks, CSS Grid, and Week 02 variables.

Recognize each subject by the problem it solves

Landmarks prevent div-soup

The frame needs to communicate the difference between controls, navigation, market content, supporting context, and status output.

Grid keeps trading zones predictable

A trading dashboard needs persistent places for watchlists, charts, screeners, selected-symbol context, news, and portfolio status.

Archetype A becomes the shell

The left rail, central workspace, top header, context side-rail, and modular stat cards form the core trading application skeleton.

Archetypes B and C become internal regions

Editorial story/status regions, filter sidebars, search, card-grid galleries, and comparison widgets live inside the dashboard workspace.

Variables prevent a second design system

Week 03 uses var(--space-md), OKLCH surface tokens, border tokens, and focus styling instead of introducing unrelated layout values.

Resiliency protects small screens

minmax(), min-width: 0, and a stacked mobile Grid keep the frame readable from narrow phones to wide monitors.

Apply the Week 03 requirements step by step

  1. Start by preserving Week 02.

    Copy the token stylesheet into /week03/, confirm Week 02 still opens, and only then begin structural layout work.

  2. Map the trading dashboard zones before writing layout CSS.

    Name the required regions: primary rail, control header, central market workspace, context drawer, and status footer.

  3. Write semantic landmarks first.

    Use <aside> for the left rail, <nav> for the trading areas, <header> for controls, <main> for market content, a second <aside> for context, and <footer> for status.

  4. Place the landmarks with CSS Grid.

    Define named grid areas so the frame can be read and rearranged without changing the HTML order.

  5. Integrate all three archetype feature groups.

    Keep Archetype A as the outer frame, then reserve internal zones for story/status content, filters, search, responsive cards, and comparison widgets.

  6. Protect narrow viewports.

    Use minmax(), min-width: 0, and a stacked media query so side rails do not create horizontal scrolling.

  7. Verify keyboard and visual behavior.

    Tab through the navigation, resize from 320px to 2560px, and confirm the structural boundaries remain visible in both themes.

week03/index.html semantic wrapper
<section class="dashboard-frame" aria-label="Trading dashboard semantic layout wireframe">
  <aside class="frame-rail" aria-label="Primary trading navigation">
    <strong>TD</strong>
    <nav aria-label="Trading dashboard areas">
      <a href="#market-workspace">Watchlist</a>
      <a href="#market-workspace">Screener</a>
      <a href="#market-workspace">Portfolio</a>
      <a href="#market-workspace">Alerts</a>
    </nav>
  </aside>

  <header class="frame-header">
    <p>Market Command Header</p>
    <form role="search" aria-label="Search symbols">
      <label for="symbol-search">Symbol</label>
      <input id="symbol-search" name="symbol-search" type="search" value="AAPL · BTC · ETH">
    </form>
  </header>

  <main class="frame-main" id="market-workspace">
    <section class="market-hero" aria-labelledby="workspace-title">
      <p class="reading-status">Session overview · Watchlist scan · Risk context</p>
      <h2 id="workspace-title">Central market workspace</h2>
      <p>Reserved for the chart, asymmetric story grid, responsive card gallery, and comparison widgets.</p>
    </section>

    <section class="stat-grid" aria-label="Modular market stat cards">
      <article>Stocks watchlist</article>
      <article>Crypto watchlist</article>
      <article>Portfolio exposure</article>
      <article>Comparison widget</article>
    </section>
  </main>

  <aside class="frame-context" aria-label="Context drawer">
    <h2>Context drawer</h2>
    <p>Reserved for quote details, news, notes, alerts, and selected-asset risk context.</p>
  </aside>

  <footer class="frame-footer">
    <p>Footer status readout · Data freshness · Secondary links</p>
  </footer>
</section>
week03/styles.css structural frame
.dashboard-frame {
  min-height: 100dvh;
  display: grid;
  grid-template-columns: minmax(8.5rem, 9.5rem) minmax(0, 1fr) minmax(11rem, 14.5rem);
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "rail header header"
    "rail main context"
    "rail footer footer";
  gap: var(--space-sm);
  padding: var(--space-sm);
  background: var(--color-background);
  color: var(--color-text);
}

.frame-rail { grid-area: rail; }
.frame-header { grid-area: header; }
.frame-main { grid-area: main; min-width: 0; }
.frame-context { grid-area: context; min-width: min(100%, 11rem); }
.frame-footer { grid-area: footer; }

.frame-rail,
.frame-header,
.frame-main,
.frame-context,
.frame-footer {
  padding: var(--space-md);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  gap: var(--space-sm);
}

@media (max-width: 58rem) {
  .dashboard-frame {
    min-height: auto;
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "rail"
      "main"
      "context"
      "footer";
  }

  .frame-rail nav {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
    gap: var(--space-sm);
  }
}
Actual Week 03 output

Semantic Trading Dashboard frame

The live Week 03 page uses this same transparent structural model: a professional trading workspace skeleton without final market data or production interaction logic.

Market Command Header

Session overview · Watchlist scan · Risk context

Central market workspace

Reserved for the chart, asymmetric story grid, responsive card gallery, and comparison widgets.

Stocks watchlist
Crypto watchlist
Portfolio exposure
Comparison widget

Footer status readout · Data freshness · Secondary links

Grid frame debugging

Why minmax() belongs in the Week 03 foundation

  1. A sidebar can collapse or force overflow if the Grid track has no useful minimum.
  2. minmax(4.75rem, 6rem) keeps the left navigation rail compact but visible.
  3. minmax(16rem, 22rem) keeps the right context drawer readable without letting it consume the whole viewport.
  4. minmax(0, 1fr) lets the central workspace shrink below its content's natural width instead of pushing the page sideways.
  5. The mobile media query stacks the header, rail, main workspace, context drawer, and footer so the frame remains usable at 320px.
03

Part 3: Co-piloting with AI

AI can draft wrappers and explain Grid behavior, but it does not get to invent the dashboard content or final layout decisions.

Allowed assistance

Use AI to draft semantic wrappers, low-specificity Grid rules, and a debugging explanation for responsive side rails.

Boundary

Do not let AI fill the dashboard with fake production content. Week 03 is a layout skeleton and should stay focused on structural zones.

Prompt 1 · Drafting semantic layout scaffolding
I am building Archetype A: a stock and crypto Trading Dashboard for my capstone project. Write the semantic HTML5 layout wrapper utilizing header, nav, main, aside, and footer. Then, write the CSS Grid rules needed to position these zones so the layout occupies exactly 100% of the viewport height. Use low-specificity CSS class selectors and bind the padding, gaps, and background colors to my existing CSS variables. The frame should also reserve internal space for Archetype B editorial/status regions and Archetype C filter, search, card-grid, and comparison-widget regions.
Prompt 2 · Grid frame debugging
[Paste your HTML & CSS draft] My aside element is collapsing to zero width when the screen gets narrow, and it is causing a horizontal scrollbar. Can you explain why this is happening within the CSS Grid formatting context and how I can set a responsive minimum width constraint on my sidebar using minmax()?
04

Part 4: Verification and submission checklist

Week 03 is complete only when the semantic frame, keyboard order, and viewport behavior are checked manually.

  • No Div-Soup Test

    Inspect the code in the editor. The outermost structural wrappers must be semantic HTML5 landmarks rather than nested generic <div> elements.

  • Keyboard Focus Check

    Press the Tab key. Navigation focus rings must highlight menu items in a logical order, and links inside <nav> must have high-contrast focus rings.

  • Viewport Resiliency

    Resize from 320px to 2560px wide. The primary layout frames should rearrange or compress elegantly without breaking structural boundaries.

  • Trading Workspace Test

    Confirm the skeleton still contains the professional trading-dashboard zones: watchlist/navigation rail, control header, main market workspace, right context drawer, modular cards, filters/search, and comparison regions.

  • Milestone Preservation Test

    Open Week 02 and Week 03 directly from their URLs. Week 03 must not modify the completed Week 02 Design System Token Page.

00

Week 04: Asymmetric responsive content grid

Week 04 keeps the Week 02 visual system and Week 03 semantic shell, then gives the central market workspace a deliberate featured-card hierarchy.

What changed this week

The previously reserved central workspace now contains six market modules: the original featured overview, stock watchlist, crypto radar, and comparison cards remain, while the Portfolio and Risk Context cards concentrate a broad technical-analysis toolkit.

What remains intentionally unchanged

The command header, left trading rail, right context drawer, footer status strip, token names, theme persistence, and every file in Weeks 02 and 03 remain preserved.

01

Part 1: Preserving your progress

Week 04 is created as a separate checkpoint by duplicating the approved Week 03 foundation and extending only the new folder.

  1. Keep Weeks 02 and 03 frozen.

    The token milestone and semantic-layout milestone remain independently accessible and are not rewritten to simulate progress.

  2. Replace only the planned Week 04 placeholder.

    /trading-dashboard/week04/ receives its own index.html, local styles.css, and required README.md.

  3. Carry the approved architecture forward.

    The Week 03 dashboard frame is the starting structure, while the Week 04 change is confined to the central <main> content grid.

02

Part 2: The Week 04 technical blueprint

The central workspace becomes a six-card asymmetric Grid with explicit hierarchy, fluid tracks, dense auto-placement, and token-controlled styling.

Recognize each subject by the problem it solves

Uniform grids hide priority

The featured span gives the visitor an immediate visual starting point instead of treating every market module as equally important.

Fixed tracks create brittle widths

Fractional tracks and minmax(0, 1fr) distribute available space without forcing page-level overflow.

Spans can leave visible holes

Dense auto-placement backfills usable cells when card sizes and available columns change.

Hardcoded gaps drift from the system

var(--space-sm) and var(--space-md) keep the new workspace aligned with Weeks 02 and 03.

Card content can widen Grid tracks

min-width: 0, wrapping, and internal overflow rules keep labels and modules inside their assigned tracks.

Desktop spans can break mobile order

At the single-column breakpoint every explicit span resets so source order becomes the visible reading order.

Apply the Week 04 requirements step by step

  1. Duplicate the Week 03 milestone into Week 04.

    Preserve the semantic frame and token names before changing the central workspace.

  2. Author six meaningful market cards.

    Keep the featured overview, stock watchlist, crypto radar, and comparison modules, then use only the Portfolio and Risk Context cards to surface a compact technical-analysis toolkit.

  3. Declare three fluid desktop tracks.

    Use repeat(3, minmax(0, 1fr)) so each column receives a fractional share and can shrink below intrinsic content width.

  4. Give the first card a two-by-two span.

    Apply both grid-column: span 2 and grid-row: span 2 to establish the requested asymmetric hierarchy.

  5. Enable dense auto-placement.

    Apply grid-auto-flow: dense on the grid container so supporting cards can fill available cells created by the hero span.

  6. Bind visual values to existing tokens.

    Use Week 02 spacing and OKLCH roles for every gap, padding value, surface, border, and text treatment.

  7. Reset the layout for narrow screens.

    Use two columns for tablet widths, one column for mobile, and reset the hero card to automatic row and column placement.

week04/index.html central workspace
<div class="market-grid" aria-label="Asymmetric market content cards">
  <article class="market-card market-card--hero">
    <p class="market-card__eyebrow">Featured market overview</p>
    <h2>Cross-market pulse</h2>
    <p>The featured card spans two columns and two rows.</p>
  </article>
  <article class="market-card"><h3>Watchlist scan</h3></article>
  <article class="market-card"><h3>Digital asset radar</h3></article>
  <article class="market-card"><h3>Technique stack</h3></article>
  <article class="market-card"><h3>Relative strength</h3></article>
  <article class="market-card market-card--alert"><h3>Confluence queue</h3></article>
</div>
week04/styles.css asymmetric grid rules
.market-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-auto-rows: minmax(9rem, auto);
  grid-auto-flow: dense;
  gap: var(--space-sm);
}

.market-card {
  min-width: 0;
  padding: var(--space-md);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface-elevated);
}

.market-card--hero {
  grid-column: span 2;
  grid-row: span 2;
}

@media (max-width: 48rem) {
  .market-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .market-card--hero { grid-column: span 2; }
}

@media (max-width: 38rem) {
  .market-grid { grid-template-columns: 1fr; }
  .market-card--hero { grid-column: auto; grid-row: auto; }
}
Actual Week 04 output

Asymmetric Trading Dashboard content workspace

This compact embedded output mirrors the live Week 04 milestone: the Week 03 shell remains visible, the original market modules return, and only Portfolio and Risk Context carry the expanded technical-analysis toolkit.

Market command header

Asymmetric workspace preview

Featured market overview

Cross-market pulse

Layout sample

The dominant card spans two columns and two rows so the primary market story receives more visual weight than supporting modules.

Track
2 columns
Depth
2 rows
Flow
Dense

Stocks

Watchlist scan

  • AAPLPrimary
  • MSFTSecondary
  • NVDACompare

Crypto

Digital asset radar

  • BTCMacro
  • ETHNetwork
  • SOLMomentum

Portfolio

Technique stack

Trend · SMA / EMA / VWAP Momentum · RSI / MACD / Stochastic Volatility · Bollinger / ATR / ADX

Comparison

Relative strength

Large capBaseline
CryptoVolatile
CashDefensive

Risk context

Confluence queue

Fibonacci · Volume Profile · OBV · Pivot Points · Support/Resistance · Candlestick Patterns · Divergence · Ichimoku · Parabolic SAR

Week 04 layout preview · Static educational content · No live market feed

Auto-placement reasoning

Why dense flow is useful—and why source order still matters

  1. The hero card reserves a two-column by two-row rectangle before smaller cards are placed.
  2. Without dense placement, the normal cursor may move forward and leave a usable earlier cell empty.
  3. grid-auto-flow: dense allows a later one-cell card to backfill that earlier opening.
  4. Dense flow can change visual placement, so the HTML source remains logically ordered and understandable without CSS.
  5. The mobile rule resets every span, removing the need for backfilling and restoring a single reading column.
03

Part 3: Co-piloting with AI

AI may propose track formulas and diagnose placement gaps, while the human remains responsible for hierarchy, content meaning, token fit, accessibility, and final verification.

Allowed assistance

Use AI to draft the asymmetric track formula, explain auto-placement, identify likely gap conditions, and suggest span-safe responsive rules.

Human responsibility

Select the featured content, preserve source order, reject unsupported trading features, integrate existing tokens, and verify the actual browser output.

Prompt 1 · Designing the asymmetric grid
Act as a senior CSS Grid systems engineer. Design an asymmetric content grid for the existing central main workspace of a stock and crypto Trading Dashboard.

Architecture requirements:

1. Preserve the supplied semantic dashboard frame and the existing Week 02 design tokens.

2. Organize six content cards in three desktop columns using minmax(0, 1fr) fractional tracks.

3. Make the first featured card span two columns and two rows while the five supporting cards occupy one track each.

4. Use grid-auto-flow: dense to reduce empty cells without changing the meaningful HTML source order.

5. Use var(--space-sm) for the grid gap, var(--space-md) for card padding, and existing OKLCH variables for surfaces, borders, and text.

6. Add a two-column tablet state and a single-column mobile state that resets every explicit card span.

7. Keep all cards overflow-safe with min-width: 0 and do not add JavaScript, live data, or trading actions.

Return only the complete CSS rules for the Week 04 market-grid and market-card components.
Prompt 2 · Preventing responsive grid gaps
Act as a CSS Grid debugging specialist. Analyze the supplied Week 04 Trading Dashboard card markup and stylesheet for empty gaps during responsive resizing.

Analysis requirements:

1. Identify which explicit column or row spans can create unfilled cells at tablet widths.

2. Explain how the CSS Grid auto-placement algorithm processes the cards in source order.

3. Show where grid-auto-flow: dense should be applied and explain what it can and cannot safely reorder visually.

4. Preserve the featured-card hierarchy while preventing overlap, clipping, and page-level horizontal overflow.

5. Recommend minmax(), min-width: 0, and span-reset rules for desktop, tablet, and single-column mobile layouts.

6. Keep spacing connected to the existing --space variables and do not introduce arbitrary pixel gaps.

Return a concise diagnosis followed by the corrected CSS only.
04

Part 4: Verification and submission checklist

Week 04 is complete only when the Grid Inspector, span behavior, card boundaries, spacing tokens, themes, and milestone preservation are checked.

  • Grid Inspector Check

    Open DevTools, highlight .market-grid, and confirm three proportional fractional tracks at a wide viewport.

  • Featured Span Check

    Confirm the first card occupies two columns and two rows without overlapping or covering a supporting card.

  • Dense Placement Check

    Resize through intermediate widths and confirm supporting cards fill available cells without a disruptive empty hole.

  • No Overlap Test

    Inspect headings, lists, technique bars, status labels, and form controls. Nothing may clip outside a card or widen the page.

  • Spacing Consistency

    Inspect computed gaps and card padding and confirm they resolve from --space-sm and --space-md.

  • Responsive Reading Order

    At the mobile breakpoint, confirm the grid becomes one column and the featured card's row and column spans reset.

  • Theme Coverage

    Check Standard, Playful Pop, Raggedy Granite, and Glossy Marble in dark and light mode across the live week and Build Story output.

  • Archive Preservation

    Open Weeks 02, 03, and 04 directly and verify that Week 04 was added beside the earlier milestones rather than overwriting them.

00

Week 05: Cascade Layers and Native CSS Nesting

Week 05 preserves the Week 04 dashboard appearance while reorganizing its local stylesheet into explicit cascade layers and browser-native nested component rules.

What changes

The source architecture becomes easier to reason about: reset rules, document defaults, layout geometry, and component styling each receive a named place in the cascade.

What stays visually locked

The Week 04 asymmetric dashboard frame, six-card hierarchy, spacing tokens, outer width, responsive breakpoints, and static market content remain the visible reference.

01

Part 1: Preserving your progress

Week 05 is created beside the approved Week 04 milestone. The previous checkpoint remains untouched for direct visual and source comparison.

  1. Duplicate the Week 04 milestone into Week 05.

    Use the approved Week 04 live output and local design values as the baseline rather than starting a new visual design.

  2. Replace only the planned Week 05 placeholder.

    /trading-dashboard/week05/ receives its own index.html, local styles.css, and required README.md.

  3. Keep Weeks 02 through 04 frozen.

    The design-system tokens, semantic frame, and asymmetric-grid checkpoints remain independently addressable and unchanged.

  4. Use Week 04 as the visual continuity oracle.

    The refactor succeeds only when Week 05 retains the approved outer geometry, dashboard hierarchy, spacing rhythm, and responsive behavior.

02

Part 2: The Week 05 technical blueprint

The Week 04 stylesheet is reorganized into four ordered layers, then component selectors are grouped with native CSS nesting without introducing Sass or a build step.

Recognize each subject by the problem it solves

Reset rules leak into component work

A dedicated reset layer keeps normalization separate from presentation decisions.

Default element styles become hard to find

The base layer owns tokens, body defaults, links, focus treatment, and heading defaults.

Layout and card styling become interleaved

The layout layer owns shells, grid areas, tracks, and responsive geometry; the components layer owns the modules placed inside them.

Repeated selectors create clutter

Native nesting groups descendants beneath their owning component without a preprocessor.

Pseudo-class states lose context

The & selector makes hover, focus, last-child, and pseudo-element relationships explicit where they are defined.

Specificity wars hide intended precedence

Named layers establish architectural priority before selector weight is considered.

Apply the Week 05 requirements step by step

  1. Clone the approved Week 04 milestone.

    Preserve the same dashboard markup, token values, page width, grid hierarchy, and responsive breakpoints in the Week 05 checkpoint.

  2. Declare the layer order first.

    Place @layer reset, base, layout, components; at the top of the local stylesheet so precedence is fixed before the blocks are populated.

  3. Sort rules by responsibility.

    Move normalization into reset, tokens and defaults into base, structural geometry into layout, and reusable UI modules into components.

  4. Nest true component relationships.

    Group child headings, labels, lists, chart bars, metrics, and control states beneath the component selector that owns them.

  5. Use & only where it expresses parent-relative behavior.

    Apply it to pseudo-classes, pseudo-elements, and modifier/state relationships without using Sass-only selector concatenation.

  6. Re-run the continuity and theme checks.

    Compare Week 04 and Week 05 at matching viewports, then test all installed style families in both dark and light mode.

week05/styles.css · complete layered and nested stylesheet
@layer reset, base, layout, components;

@layer reset {
  *, *::before, *::after {
    box-sizing: border-box;
  }

  body {
    margin: 0;
  }
}

@layer base {
  :root {
    color-scheme: light;

    --color-primary: oklch(0.52 0.14 55);
    --color-secondary: oklch(0.48 0.09 205);
    --color-background: oklch(0.97 0.008 255);
    --color-surface: oklch(0.995 0.002 255);
    --color-surface-elevated: oklch(0.95 0.015 255);
    --color-border: oklch(0.84 0.025 255);
    --color-text: oklch(0.22 0.025 255);
    --color-text-muted: oklch(0.45 0.025 255);
    --color-on-primary: oklch(0.995 0.002 255);
    --color-positive: oklch(0.48 0.11 145);
    --color-attention: oklch(0.56 0.14 68);
    --color-shadow: oklch(0.22 0.025 255 / 0.14);

    --size-base: 1rem;
    --size-heading-md: clamp(1.35rem, 1.18rem + 0.75vw, 2rem);
    --size-heading-lg: clamp(1.75rem, 1.3099rem + 1.8779vw, 3rem);

    --space-xs: 0.5rem;
    --space-sm: 0.75rem;
    --space-md: 1rem;
    --space-lg: 1.5rem;

    --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --font-mono: "Fira Code", Consolas, monospace;
    --radius-sm: 0.4rem;
    --radius-lg: 0.8rem;
    --max-width: var(--portfolio-content-max, 72rem);
  }

  html {
    scroll-behavior: smooth;

    &[data-theme="dark"] {
      color-scheme: dark;

      --color-primary: oklch(0.72 0.16 55);
      --color-secondary: oklch(0.78 0.12 205);
      --color-background: oklch(0.15 0.02 255);
      --color-surface: oklch(0.20 0.02 255);
      --color-surface-elevated: oklch(0.24 0.025 255);
      --color-border: oklch(0.33 0.025 255);
      --color-text: oklch(0.95 0.01 255);
      --color-text-muted: oklch(0.72 0.02 255);
      --color-on-primary: oklch(0.16 0.02 255);
      --color-positive: oklch(0.76 0.14 145);
      --color-attention: oklch(0.78 0.14 68);
      --color-shadow: oklch(0 0 0 / 0.42);
    }
  }

  body {
    background:
      radial-gradient(circle at 10% 5%, color-mix(in oklch, var(--color-primary) 16%, transparent), transparent 28rem),
      radial-gradient(circle at 92% 25%, color-mix(in oklch, var(--color-secondary) 12%, transparent), transparent 30rem),
      var(--color-background);
    color: var(--color-text);
    font-family: var(--font-sans);
    font-size: var(--size-base);
    line-height: 1.65;
  }

  a {
    color: inherit;
  }

  :where(a, button, input):focus-visible {
    outline: 0.2rem solid var(--color-secondary);
    outline-offset: 0.2rem;
  }

  h1 {
    max-width: 19ch;
    margin: var(--space-sm) 0;
    font-size: var(--size-heading-lg);
    line-height: 1.05;
    letter-spacing: -0.04em;
    text-wrap: balance;
  }
}

@layer layout {
  .page-shell {
    width: min(calc(100% - 2rem), var(--max-width));
    margin-inline: auto;
    padding-bottom: 3rem;
  }

  main {
    display: grid;
    gap: var(--space-lg);
    margin-top: var(--space-lg);
  }

  .progress-grid,
  .architecture-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
    gap: var(--space-md);
  }

  .dashboard-frame {
    display: grid;
    grid-template-columns: minmax(8.5rem, 9.5rem) minmax(0, 1fr) minmax(11rem, 14.5rem);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "rail header header"
      "rail main context"
      "rail footer footer";
    gap: var(--space-sm);
    min-height: min(48rem, 100dvh);

    .frame-rail { grid-area: rail; }
    .frame-header { grid-area: header; }
    .frame-main { grid-area: main; }
    .frame-context { grid-area: context; }
    .frame-footer { grid-area: footer; }
  }

  .market-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-rows: minmax(9rem, auto);
    grid-auto-flow: dense;
    gap: var(--space-sm);
  }

  @media (max-width: 66rem) {
    .dashboard-frame {
      min-height: auto;
      grid-template-columns: 1fr;
      grid-template-areas: "header" "rail" "main" "context" "footer";
    }

    .frame-rail nav {
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
    }
  }

  @media (max-width: 48rem) {
    .market-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }

  @media (max-width: 38rem) {
    .market-grid {
      grid-template-columns: 1fr;
    }
  }
}

@layer components {
  .skip-link {
    position: fixed;
    z-index: 20;
    left: var(--space-md);
    top: var(--space-md);
    transform: translateY(-200%);
    padding: var(--space-sm) var(--space-md);
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-weight: 900;

    &:focus {
      transform: translateY(0);
    }
  }

  .token-hero {
    padding: clamp(1.5rem, 1rem + 2.5vw, 3.5rem);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: linear-gradient(135deg, color-mix(in oklch, var(--color-primary) 12%, transparent), transparent 50%), var(--color-surface);
    box-shadow: 0 1rem 2.5rem var(--color-shadow);

    > p:last-child {
      max-width: 65ch;
      color: var(--color-text-muted);
      font-size: clamp(1.05rem, 0.98rem + 0.35vw, 1.25rem);
    }

    code {
      color: var(--color-secondary);
      font-family: var(--font-mono);
    }
  }

  .eyebrow {
    margin: 0;
    color: var(--color-secondary);
    font-family: var(--font-mono);
    font-size: 0.85rem;
    font-weight: 900;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .token-section {
    min-width: 0;
    padding: clamp(1rem, 0.75rem + 1.25vw, 2rem);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    box-shadow: 0 0.75rem 2rem var(--color-shadow);
  }

  .section-heading {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-md);
    align-items: start;
    margin-bottom: var(--space-lg);

    > span {
      display: grid;
      place-items: center;
      width: 2.75rem;
      aspect-ratio: 1;
      border-radius: 50%;
      background: var(--color-primary);
      color: var(--color-on-primary);
      font-family: var(--font-mono);
      font-weight: 900;
    }

    h2 {
      margin: 0;
      font-size: var(--size-heading-md);
      line-height: 1.15;
    }

    p {
      margin: var(--space-xs) 0 0;
      color: var(--color-text-muted);
    }
  }

  :is(.progress-card, .architecture-card) {
    min-width: 0;
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface-elevated);

    code {
      display: inline-block;
      margin-bottom: var(--space-xs);
      color: var(--color-secondary);
      font-family: var(--font-mono);
      font-weight: 800;
    }

    h3 {
      margin: 0 0 var(--space-xs);
    }

    p {
      margin: 0;
      color: var(--color-text-muted);
    }
  }

  .progress-card {
    &.progress-card--current {
      border-color: var(--color-primary);
      background: linear-gradient(135deg, color-mix(in oklch, var(--color-primary) 13%, transparent), transparent 55%), var(--color-surface-elevated);
      box-shadow: inset 0.28rem 0 var(--color-primary);
    }
  }

  pre {
    overflow-x: auto;
    margin: var(--space-lg) 0 0;
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: color-mix(in oklch, var(--color-background) 80%, black);
    color: var(--color-text);
    font: 0.9rem/1.7 var(--font-mono);
  }

  .checklist {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 23rem), 1fr));
    gap: var(--space-sm);
    padding: 0;
    list-style: none;

    li {
      position: relative;
      min-width: 0;
      padding: var(--space-md) var(--space-md) var(--space-md) 3rem;
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
      background: var(--color-surface-elevated);

      &::before {
        content: "✓";
        position: absolute;
        left: var(--space-md);
        color: var(--color-positive);
        font-weight: 900;
      }
    }

    code {
      color: var(--color-secondary);
      font-family: var(--font-mono);
    }
  }

  .resiliency-note {
    margin-top: var(--space-md);
    padding: var(--space-md);
    border-left: 0.3rem solid var(--color-primary);
    background: var(--color-surface-elevated);

    p {
      margin-bottom: 0;
      color: var(--color-text-muted);
    }
  }

  footer {
    padding: var(--space-lg) 0;
    color: var(--color-text-muted);
    text-align: center;
    font-family: var(--font-mono);
  }

  .dashboard-frame {
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background:
      linear-gradient(135deg, color-mix(in oklch, var(--color-primary) 10%, transparent), transparent 55%),
      var(--color-surface-elevated);
  }

  :is(.frame-rail, .frame-header, .frame-main, .frame-context, .frame-footer) {
    min-width: 0;
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: color-mix(in oklch, var(--color-surface) 90%, transparent);
  }

  .frame-rail {
    strong {
      display: grid;
      place-items: center;
      width: 3rem;
      aspect-ratio: 1;
      margin-bottom: var(--space-md);
      border-radius: var(--radius-sm);
      background: var(--color-primary);
      color: var(--color-on-primary);
      font-family: var(--font-mono);
    }

    nav {
      display: grid;
      gap: var(--space-xs);
    }

    a {
      display: block;
      width: 100%;
      padding: var(--space-xs) var(--space-sm);
      border: 1px solid transparent;
      border-radius: var(--radius-sm);
      background: color-mix(in oklch, var(--color-surface-elevated) 72%, transparent);
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.78rem;
      font-weight: 800;
      text-decoration: none;

      &:focus-visible,
      &:hover {
        border-color: var(--color-primary);
        background: color-mix(in oklch, var(--color-primary) 16%, var(--color-surface));
        color: var(--color-text);
      }
    }
  }

  .frame-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-md);

    p {
      margin: 0;
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-weight: 800;
    }

    form {
      display: flex;
      align-items: center;
      gap: var(--space-sm);
    }

    label {
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.78rem;
      font-weight: 800;
      text-transform: uppercase;
    }

    input {
      max-width: 13rem;
      padding: var(--space-xs) var(--space-sm);
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
      background: var(--color-background);
      color: var(--color-text);
      font: inherit;
    }
  }

  .frame-footer p {
    margin: 0;
    color: var(--color-text-muted);
    font-family: var(--font-mono);
    font-weight: 800;
  }

  .frame-kicker {
    color: var(--color-secondary) !important;
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .frame-context {
    h2 {
      margin: var(--space-xs) 0;
      font-size: var(--size-heading-md);
      line-height: 1.15;
    }

    > p:not(.frame-kicker) {
      margin: 0;
      color: var(--color-text-muted);
    }
  }

  .context-list {
    display: grid;
    gap: var(--space-xs);
    margin: var(--space-md) 0 0;
    padding: 0;
    list-style: none;

    li {
      padding: var(--space-xs) var(--space-sm);
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.78rem;
    }
  }

  .market-card {
    min-width: 0;
    overflow: hidden;
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface-elevated);

    &.market-card--hero {
      grid-column: span 2;
      grid-row: span 2;
      display: grid;
      align-content: space-between;
      gap: var(--space-md);
      background: linear-gradient(145deg, color-mix(in oklch, var(--color-secondary) 12%, transparent), transparent 50%), var(--color-surface-elevated);
    }

    &.market-card--alert {
      border-color: color-mix(in oklch, var(--color-attention) 70%, var(--color-border));

      > p:last-child {
        margin: 0;
        color: var(--color-text-muted);
      }
    }

    .market-card__heading {
      display: flex;
      align-items: start;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: var(--space-sm);
    }

    .market-card__eyebrow {
      margin: 0 0 var(--space-xs);
      color: var(--color-secondary);
      font-family: var(--font-mono);
      font-size: 0.72rem;
      font-weight: 900;
      letter-spacing: 0.07em;
      text-transform: uppercase;
    }

    h2,
    h3 {
      margin: 0;
      line-height: 1.15;
    }

    h2 {
      font-size: var(--size-heading-md);
    }

    h3 {
      font-size: clamp(1.05rem, 0.97rem + 0.4vw, 1.3rem);
    }

    .market-card__status {
      padding: 0.25rem 0.5rem;
      border: 1px solid var(--color-border);
      border-radius: 999px;
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.68rem;
      font-weight: 800;
      text-transform: uppercase;
    }

    .market-card__lead {
      margin: 0;
      color: var(--color-text-muted);
    }
  }

  .market-chart {
    display: flex;
    align-items: end;
    gap: var(--space-xs);
    min-height: 8.5rem;
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: color-mix(in oklch, var(--color-background) 72%, transparent);

    span {
      flex: 1;
      min-width: 0.35rem;
      height: var(--bar-size);
      border-radius: 0.25rem 0.25rem 0 0;
      background: linear-gradient(180deg, var(--color-secondary), var(--color-primary));
    }
  }

  .market-metrics {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-xs);
    margin: 0;

    div {
      min-width: 0;
      padding: var(--space-xs);
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
    }

    dt {
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.68rem;
      text-transform: uppercase;
    }

    dd {
      margin: 0.2rem 0 0;
      font-weight: 800;
    }
  }

  .market-list {
    display: grid;
    gap: var(--space-xs);
    margin: var(--space-md) 0 0;
    padding: 0;
    list-style: none;

    li {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--space-sm);
      padding-block: var(--space-xs);
      border-bottom: 1px solid var(--color-border);

      &:last-child {
        border-bottom: 0;
      }
    }

    strong {
      color: var(--color-positive);
      font-family: var(--font-mono);
      font-size: 0.72rem;
    }
  }

  .allocation-bars {
    display: grid;
    gap: var(--space-sm);
    margin-top: var(--space-md);

    span {
      position: relative;
      display: block;
      overflow: hidden;
      padding: 0.35rem var(--space-xs);
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
      color: var(--color-text);
      font-family: var(--font-mono);
      font-size: 0.72rem;
      isolation: isolate;

      &::before {
        content: "";
        position: absolute;
        inset: 0 auto 0 0;
        z-index: -1;
        width: var(--allocation);
        background: color-mix(in oklch, var(--color-primary) 26%, transparent);
      }
    }
  }

  .comparison-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    margin-top: var(--space-xs);
    padding-block: var(--space-xs);
    border-bottom: 1px solid var(--color-border);
    color: var(--color-text-muted);

    &:last-child {
      border-bottom: 0;
    }

    strong {
      color: var(--color-positive);
      font-family: var(--font-mono);
      font-size: 0.72rem;
    }
  }

  @media (max-width: 48rem) {
    .market-card.market-card--hero {
      grid-column: span 2;
    }
  }

  @media (max-width: 38rem) {
    .section-heading {
      grid-template-columns: 1fr;
    }

    .frame-header,
    .frame-header form {
      align-items: stretch;
      flex-direction: column;
    }

    .frame-header input {
      width: 100%;
      max-width: none;
    }

    .market-card.market-card--hero {
      grid-column: auto;
      grid-row: auto;
    }

    .market-metrics {
      grid-template-columns: 1fr;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  @layer base {
    html {
      scroll-behavior: auto;
    }
  }

  @layer reset {
    *, *::before, *::after {
      transition-duration: 0.01ms !important;
    }
  }
}
Actual Week 05 output

The visible dashboard remains the Week 04 design.

The refactor changes CSS organization, not the approved user-facing composition. The same asymmetric frame is embedded here as the continuity proof.

Market command header

Asymmetric workspace preview

Featured market overview

Cross-market pulse

Layout sample

The dominant card spans two columns and two rows so the primary market story receives more visual weight than supporting modules.

Track
2 columns
Depth
2 rows
Flow
Dense

Stocks

Watchlist scan

  • AAPLPrimary
  • MSFTSecondary
  • NVDACompare

Crypto

Digital asset radar

  • BTCMacro
  • ETHNetwork
  • SOLMomentum

Portfolio

Technique stack

Trend · SMA / EMA / VWAP Momentum · RSI / MACD / Stochastic Volatility · Bollinger / ATR / ADX

Comparison

Relative strength

Large capBaseline
CryptoVolatile
CashDefensive

Risk context

Confluence queue

Fibonacci · Volume Profile · OBV · Pivot Points · Support/Resistance · Candlestick Patterns · Divergence · Ichimoku · Parabolic SAR

Week 05 refactor preview · Static educational content · No live market feed

Cascade reasoning

Why the declared layer order makes the refactor easier to maintain

  1. reset establishes structural normalization without competing with later presentation rules.
  2. base defines the token system and document defaults that later layers consume.
  3. layout owns macro geometry and responsive structure without carrying card-specific presentation.
  4. components is declared last, so normal component declarations outrank earlier author layers regardless of selector weight.
  5. Theme package styles remain unlayered and load after the weekly stylesheet, preserving the repository-wide style-family override contract.
03

Part 3: Co-piloting with AI

AI can help classify existing rules and rewrite component relationships, while the human remains responsible for preserving visual continuity, selector meaning, cascade safety, and final browser verification.

Allowed assistance

Use AI to group existing selectors into architectural layers, identify redundant selector repetition, and suggest native nesting structures for clear parent-child relationships.

Human responsibility

Protect the Week 04 visual baseline, reject nesting that changes selector semantics, verify layer precedence in DevTools, and confirm themes still override the weekly token contract correctly.

Prompt 1 · Refactoring CSS to cascade layers
Act as a senior CSS architecture engineer. Analyze the supplied Week 04 Trading Dashboard stylesheet and reorganize the existing rules into four named cascade layers without changing the rendered design.

Architecture requirements:

1. Declare the precedence order exactly as @layer reset, base, layout, components; before defining the layer blocks.

2. Place structural normalization such as box sizing and the body margin reset in the reset layer.

3. Place design tokens, color-mode defaults, typography defaults, links, focus behavior, and global heading defaults in the base layer.

4. Place page-shell sizing, dashboard grid areas, responsive track formulas, and other macro geometry in the layout layer.

5. Place cards, controls, labels, market widgets, verification items, and interactive component states in the components layer.

6. Preserve every existing Week 04 value that controls visible geometry, spacing, typography, colors, borders, and responsive behavior unless moving it is required for the layer architecture.

7. Do not add a framework, preprocessor, JavaScript dependency, or new visual feature.

Return only the complete refactored CSS stylesheet.
Prompt 2 · Refactoring components to native nesting
Act as a native CSS nesting specialist. Analyze the supplied Week 05 component rules and refactor repeated parent-child selectors into browser-native nested CSS while preserving selector meaning and computed output.

Implementation requirements:

1. Group true child selectors beneath the component that owns them, especially the frame rail, section heading, market cards, lists, metrics, chart bars, and allocation bars.

2. Use the & nesting selector for pseudo-classes and pseudo-elements such as &:hover, &:focus-visible, &:last-child, and &::before when the relationship is relative to the parent.

3. Do not use Sass-only parent-selector concatenation such as &--modifier; use valid native selector relationships instead.

4. Keep declarations before nested rules where practical and preserve the original selector semantics.

5. Preserve the Week 04 visual values, layout behavior, responsive breakpoints, theme token names, and accessibility behavior.

6. Do not introduce a CSS preprocessor, build step, JavaScript behavior, or unrelated redesign.

Return the corrected native CSS nesting rules and a concise note identifying any selector that should remain unnested.
04

Part 4: Verification and submission checklist

Week 05 is complete only when layer labels, native nesting syntax, visual continuity, responsive behavior, themes, and archive preservation are verified.

  • Visual Continuity Test

    Compare the Week 04 and Week 05 dashboard outputs at matching desktop, tablet, and mobile widths. The refactor must not create an intentional redesign.

  • Inspector Layer Audit

    Select a market-card descendant in DevTools and confirm the relevant rules are identified inside the components cascade layer.

  • Layer Order Check

    Confirm the stylesheet begins with @layer reset, base, layout, components; and each named block exists.

  • Nesting Syntax Check

    Confirm the browser parses nested child rules and &-relative pseudo-classes natively with no Sass-only concatenation or build step.

  • Responsive Geometry Check

    Confirm the page shell, hero measure, dashboard tracks, featured-card spans, gaps, and single-column fallback match the approved Week 04 behavior.

  • Theme Coverage

    Check Standard, Playful Pop, Raggedy Granite, Glossy Marble, and Luminous Midnight in dark and light mode across the live Week 05 page and Build Story output.

  • Archive Preservation

    Open Weeks 02, 03, and 04 directly and verify that Week 05 was added beside them rather than rewriting a completed milestone.

00

Week 06: Component-Level Flexibility with CSS Container Queries

The Week 05 dashboard remains the foundation while one reusable market component learns to respond to its own parent width.

What changed

A reusable market brief is placed in both the wide market workspace and the narrow research drawer. Identical markup chooses horizontal or stacked internals from container width.

What stayed locked

Weeks 02–05, the command-center shell, asymmetric market grid, outer width, design tokens, cascade-layer order, native nesting, and static educational data remain preserved.

01

Part 1: Preserving Your Progress (No Overwriting)

Week 06 is created beside Week 05 rather than replacing any completed checkpoint.

  1. Duplicate the approved Week 05 milestone.

    Carry forward the layered stylesheet, native nesting, command-center frame, asymmetric market grid, tokens, and responsive macro layout.

  2. Replace only the Week 06 placeholder.

    trading-dashboard/week06/ receives its own live page, local stylesheet, and README.

  3. Freeze Weeks 02 through 05.

    Do not back-port the new component-query work into historical milestone directories.

  4. Preserve approved outer geometry.

    The experiment lives inside the existing content field rather than widening the page or changing the dashboard shell.

02

Part 2: The Week 06 technical blueprint

Named inline-size containers move responsive responsibility from the viewport to the reusable component's actual placement.

Recognize each subject by the problem it solves

One viewport breakpoint cannot describe every placement

Container queries react to the actual parent slot.

A narrow drawer can squash a row card

The base state stacks the visual above the copy.

A wide slot can waste horizontal room

The 500px query switches the same component to a horizontal composition.

Nested containers can create ambiguous ownership

A named query context targets the intended placement wrapper.

Fixed internal spacing feels brittle

Bounded cqw values scale component rhythm without runaway growth.

Macro and micro responsiveness can become tangled

Viewport media queries remain for dashboard tracks while component direction belongs to @container.

Apply the Week 06 requirements step by step

  1. Clone Week 05.

    Retain its layered/nested CSS, dashboard frame, asymmetric grid, tokens, and macro breakpoints.

  2. Establish a named containment context.

    Set each .component-slot to container: market-card-slot / inline-size.

  3. Author a narrow-first component.

    The base .adaptive-market-card uses a vertical flex column.

  4. Switch only through the parent condition.

    At @container market-card-slot (min-width: 500px), change the card to a horizontal row.

  5. Use bounded container units.

    Apply cqw through clamp() for internal gap, padding, and type.

  6. Run the placement test.

    Keep identical component markup in the main workspace and context drawer at the same viewport width.

  7. Keep media queries at the page level.

    Retain existing viewport queries for macro frame/grid geometry, not for the adaptive card's internal flex-direction.

week06/index.html · complete live milestone
<!DOCTYPE html>
<html lang="en" data-theme="dark" data-style-theme="standard">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="Week 06 component-level flexibility using CSS Container Queries for the stock and crypto Trading Dashboard capstone.">
  <meta name="theme-color" content="#071019" id="themeColor">
  <title>Week 06 | Trading Dashboard Container Queries</title>
  <link rel="stylesheet" href="styles.css">
  <link rel="stylesheet" href="../../styles/shared/navigation.css">
  <script src="../../site-navigation.js" defer></script>

  <!-- Theme packages: every theme owns its CSS, metadata, and visual assets. -->
  <script src="../../styles/themes/theme-registry.js"></script>
  <script src="../../styles/themes/standard/theme-config.js"></script>
  <script src="../../styles/themes/playful-pop/theme-config.js"></script>
  <script src="../../styles/themes/raggedy-granite/theme-config.js"></script>
  <script src="../../styles/themes/glossy-marble/theme-config.js"></script>
  <script src="../../styles/themes/luminous-midnight/theme-config.js"></script>
  <script src="../../styles/themes/gothic-stickerboard/theme-config.js"></script>
  <link rel="stylesheet" href="../../styles/themes/standard/theme.css" data-style-theme-stylesheet data-active-style-theme="standard">
  <script src="../../theme.js"></script>
</head>
<body class="trading-dashboard-week06-page">
  <a class="skip-link" href="#main-content">Skip to the Week 06 container-query milestone</a>
  <div data-portfolio-navigation data-root="../../" data-current-page="week06"></div>

  <div class="page-shell">
    <header class="token-hero">
      <p class="eyebrow">Week 06 · Component-Level Flexibility with CSS Container Queries</p>
      <h1>The Trading Dashboard cards now adapt to the space they receive, not only to the viewport.</h1>
      <p>
        This milestone duplicates the approved Week 05 output, keeps its layered and nested CSS architecture,
        then establishes inline-size container contexts so one reusable market card can stack in a narrow drawer and reflow horizontally in a wide workspace.
      </p>
    </header>

    <main id="main-content">
      <section class="token-section" aria-labelledby="progress-title">
        <div class="section-heading"><span>01</span><div><h2 id="progress-title">Progress preserved, components made context-aware</h2><p>Weeks 02 through 05 remain frozen checkpoints. Week 06 adds component-level responsiveness without replacing the approved dashboard foundation.</p></div></div>
        <div class="progress-grid">
          <article class="progress-card"><code>Week 02</code><h3>Design system tokens</h3><p>OKLCH roles, fluid type, spacing variables, borders, focus states, and theme contracts remain the visual source of truth.</p></article>
          <article class="progress-card"><code>Week 03</code><h3>Semantic dashboard frame</h3><p>The command header, left rail, market workspace, context drawer, and status footer remain structurally intact.</p></article>
          <article class="progress-card"><code>Week 04</code><h3>Asymmetric content hierarchy</h3><p>The six-card market workspace and featured two-by-two market story remain preserved.</p></article>
          <article class="progress-card"><code>Week 05</code><h3>Layered and nested CSS</h3><p>The reset, base, layout, and components layers plus native nesting remain the Week 06 stylesheet foundation.</p></article>
          <article class="progress-card progress-card--current"><code>Week 06</code><h3>Container-relative cards</h3><p>The same reusable component now chooses stacked or horizontal internals from its direct container width.</p></article>
        </div>
      </section>

      <section class="token-section" aria-labelledby="workspace-title">
        <div class="section-heading"><span>02</span><div><h2 id="workspace-title">Placement test: one component, two container widths</h2><p>The adaptive card appears in both the wide market workspace and the narrow research drawer. Its internal layout changes through <code>@container</code>, not through a viewport media query.</p></div></div>
        <section class="dashboard-frame" aria-label="Week 06 container-aware Trading Dashboard workspace">
          <aside class="frame-rail" aria-label="Primary trading navigation">
            <strong>TD</strong>
            <nav aria-label="Trading dashboard areas">
              <a href="#market-workspace">Watchlist</a>
              <a href="#market-workspace">Screener</a>
              <a href="#market-workspace">Portfolio</a>
              <a href="#market-workspace">Alerts</a>
            </nav>
          </aside>

          <header class="frame-header">
            <div><p class="frame-kicker">Market command header</p><strong>Container-aware workspace preview</strong></div>
            <form role="search" aria-label="Search symbols">
              <label for="symbol-search">Symbol</label>
              <input id="symbol-search" name="symbol-search" type="search" value="AAPL · BTC · ETH">
            </form>
          </header>

          <main class="frame-main" id="market-workspace">
            <div class="market-grid" aria-label="Asymmetric market content cards">
              <article class="market-card market-card--hero">
                <div class="market-card__heading"><div><p class="market-card__eyebrow">Featured market overview</p><h2>Cross-market pulse</h2></div><span class="market-card__status">Layout sample</span></div>
                <p class="market-card__lead">The Week 04 asymmetric hierarchy remains in place while Week 06 adds a separate context-aware component test below it.</p>
                <div class="market-chart" aria-label="Decorative market trend placeholder"><span style="--bar-size: 42%"></span><span style="--bar-size: 58%"></span><span style="--bar-size: 48%"></span><span style="--bar-size: 74%"></span><span style="--bar-size: 66%"></span><span style="--bar-size: 88%"></span><span style="--bar-size: 76%"></span></div>
                <dl class="market-metrics"><div><dt>Track</dt><dd>2 columns</dd></div><div><dt>Depth</dt><dd>2 rows</dd></div><div><dt>Flow</dt><dd>Dense</dd></div></dl>
              </article>
              <article class="market-card"><p class="market-card__eyebrow">Stocks</p><h3>Watchlist scan</h3><ul class="market-list"><li><span>AAPL</span><strong>Primary</strong></li><li><span>MSFT</span><strong>Secondary</strong></li><li><span>NVDA</span><strong>Compare</strong></li></ul></article>
              <article class="market-card"><p class="market-card__eyebrow">Crypto</p><h3>Digital asset radar</h3><ul class="market-list"><li><span>BTC</span><strong>Macro</strong></li><li><span>ETH</span><strong>Network</strong></li><li><span>SOL</span><strong>Momentum</strong></li></ul></article>
              <article class="market-card"><p class="market-card__eyebrow">Portfolio</p><h3>Technique stack</h3><div class="allocation-bars" aria-label="Compact technical-analysis technique groups"><span style="--allocation: 88%">Trend · SMA / EMA / VWAP</span><span style="--allocation: 70%">Momentum · RSI / MACD / Stochastic</span><span style="--allocation: 54%">Volatility · Bollinger / ATR / ADX</span></div></article>
              <article class="market-card"><p class="market-card__eyebrow">Comparison</p><h3>Relative strength</h3><div class="comparison-row"><span>Large cap</span><strong>Baseline</strong></div><div class="comparison-row"><span>Crypto</span><strong>Volatile</strong></div><div class="comparison-row"><span>Cash</span><strong>Defensive</strong></div></article>
              <article class="market-card market-card--alert"><p class="market-card__eyebrow">Risk context</p><h3>Confluence queue</h3><p>Fibonacci · Volume Profile · OBV · Pivot Points · Support/Resistance · Candlestick Patterns · Divergence · Ichimoku · Parabolic SAR</p></article>
            </div>

            <div class="component-placement-grid" aria-label="Wide-container adaptive card test">
              <div class="component-slot">
                <article class="adaptive-market-card">
                  <div class="adaptive-market-card__visual" aria-label="Decorative cross-market bars"><span style="--bar-size: 44%"></span><span style="--bar-size: 68%"></span><span style="--bar-size: 55%"></span><span style="--bar-size: 86%"></span></div>
                  <div class="adaptive-market-card__content"><p class="adaptive-market-card__eyebrow">Wide placement · main workspace</p><h3>Context-aware market brief</h3><p>At 500px or wider this reusable card becomes a horizontal composition, with the visual beside the copy.</p></div>
                </article>
              </div>
            </div>
          </main>

          <aside class="frame-context" aria-label="Context drawer">
            <p class="frame-kicker">Selected asset context</p>
            <h2>Research drawer</h2>
            <p>Quote details, notes, headlines, and risk context remain separate from the primary asymmetric workspace.</p>
            <ul class="context-list"><li>Quote snapshot</li><li>Research notes</li><li>Alert thresholds</li></ul>
            <div class="component-slot" style="margin-top: var(--space-md);">
              <article class="adaptive-market-card">
                <div class="adaptive-market-card__visual" aria-label="Decorative cross-market bars"><span style="--bar-size: 44%"></span><span style="--bar-size: 68%"></span><span style="--bar-size: 55%"></span><span style="--bar-size: 86%"></span></div>
                <div class="adaptive-market-card__content"><p class="adaptive-market-card__eyebrow">Narrow placement · context drawer</p><h3>Context-aware market brief</h3><p>Below 500px the same component remains stacked, keeping the visual above the copy without any card-alignment media query.</p></div>
              </article>
            </div>
          </aside>

          <footer class="frame-footer"><p>Week 06 container-query preview · Static educational content · No live market feed</p></footer>
        </section>
      </section>

      <section class="token-section" aria-labelledby="architecture-title">
        <div class="section-heading"><span>03</span><div><h2 id="architecture-title">Container context and component query contract</h2><p>Page-level media queries still control macro dashboard tracks, while the Week 06 reusable card owns its internal response through a named inline-size container.</p></div></div>
        <div class="architecture-grid">
          <article class="architecture-card"><code>container: market-card-slot / inline-size</code><h3>Establish the context</h3><p>Each placement wrapper becomes an inline-size query container without changing the reusable card markup.</p></article>
          <article class="architecture-card"><code>@container</code><h3>Query the parent</h3><p>The component responds to the nearest named container instead of checking the browser viewport.</p></article>
          <article class="architecture-card"><code>min-width: 500px</code><h3>Switch layout mode</h3><p>The base card stacks vertically; a sufficiently wide container changes it to a horizontal row.</p></article>
          <article class="architecture-card"><code>cqw</code><h3>Micro-scale with context</h3><p>Padding, gaps, and type use bounded container-relative units so the card can breathe proportionally inside either placement.</p></article>
          <article class="architecture-card"><code>@media</code><h3>Keep macro layout separate</h3><p>Existing viewport queries still handle the overall dashboard frame and grid tracks; they do not control the new card's internal direction.</p></article>
          <article class="architecture-card"><code>same markup</code><h3>Placement independence</h3><p>The main and context versions are identical components. Only their available container width changes the presentation.</p></article>
        </div>
        <pre><code>.component-slot {
  container: market-card-slot / inline-size;
}

.adaptive-market-card {
  display: flex;
  flex-direction: column;
  gap: clamp(0.7rem, 3cqw, 1.15rem);
  padding: clamp(0.8rem, 4cqw, 1.35rem);
}

@container market-card-slot (min-width: 500px) {
  .adaptive-market-card {
    flex-direction: row;
    align-items: center;
  }
}</code></pre>
      </section>

      <section class="token-section" aria-labelledby="verification-title">
        <div class="section-heading"><span>04</span><div><h2 id="verification-title">Week 06 verification</h2><p>The milestone is complete only when the same component visibly changes layout from parent width, not viewport-dependent card alignment.</p></div></div>
        <ul class="checklist">
          <li>Confirm Week 06 exists beside Week 05 and Weeks 02–05 remain unchanged historical checkpoints.</li>
          <li>Inspect both <code>.component-slot</code> wrappers and confirm each establishes <code>container: market-card-slot / inline-size</code>.</li>
          <li>At desktop width, confirm the main-workspace adaptive card is horizontal while the context-drawer copy of the same component remains vertically stacked.</li>
          <li>Resize the page and confirm the component changes when its own container crosses 500px, not because a card-alignment <code>@media</code> rule fires.</li>
          <li>Inspect the adaptive card rules and confirm no viewport media query sets its <code>flex-direction</code>.</li>
          <li>Confirm bounded <code>cqw</code> values are used for component spacing or type without producing overflow at narrow widths.</li>
          <li>Switch Standard, Playful Pop, Raggedy Granite, Glossy Marble, Luminous Midnight, and Gothic Stickerboard between dark and light modes and confirm the complete Week 06 page remains readable and themed.</li>
        </ul>
        <div class="resiliency-note"><strong>Scope boundary</strong><p>Week 06 adds component-level flexibility only. It does not add live prices, broker actions, production feeds, authentication, or trading logic.</p></div>
      </section>
    </main>

    <footer>
      <p class="footer-copyright">&copy; 2026 Dmitriy Chernichenko.</p>
      <p>Weeks 02 through 05 remain preserved. Week 06 adds container-aware reusable components to the existing Trading Dashboard foundation.</p>
    </footer>
  </div>
</body>
</html>
week06/styles.css · complete local stylesheet
@layer reset, base, layout, components;

@layer reset {
  *, *::before, *::after {
    box-sizing: border-box;
  }

  body {
    margin: 0;
  }
}

@layer base {
  :root {
    color-scheme: light;

    --color-primary: oklch(0.52 0.14 55);
    --color-secondary: oklch(0.48 0.09 205);
    --color-background: oklch(0.97 0.008 255);
    --color-surface: oklch(0.995 0.002 255);
    --color-surface-elevated: oklch(0.95 0.015 255);
    --color-border: oklch(0.84 0.025 255);
    --color-text: oklch(0.22 0.025 255);
    --color-text-muted: oklch(0.45 0.025 255);
    --color-on-primary: oklch(0.995 0.002 255);
    --color-positive: oklch(0.48 0.11 145);
    --color-attention: oklch(0.56 0.14 68);
    --color-shadow: oklch(0.22 0.025 255 / 0.14);

    --size-base: 1rem;
    --size-heading-md: clamp(1.35rem, 1.18rem + 0.75vw, 2rem);
    --size-heading-lg: clamp(1.75rem, 1.3099rem + 1.8779vw, 3rem);

    --space-xs: 0.5rem;
    --space-sm: 0.75rem;
    --space-md: 1rem;
    --space-lg: 1.5rem;

    --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --font-mono: "Fira Code", Consolas, monospace;
    --radius-sm: 0.4rem;
    --radius-lg: 0.8rem;
    --max-width: var(--portfolio-content-max, 72rem);
  }

  html {
    scroll-behavior: smooth;

    &[data-theme="dark"] {
      color-scheme: dark;

      --color-primary: oklch(0.72 0.16 55);
      --color-secondary: oklch(0.78 0.12 205);
      --color-background: oklch(0.15 0.02 255);
      --color-surface: oklch(0.20 0.02 255);
      --color-surface-elevated: oklch(0.24 0.025 255);
      --color-border: oklch(0.33 0.025 255);
      --color-text: oklch(0.95 0.01 255);
      --color-text-muted: oklch(0.72 0.02 255);
      --color-on-primary: oklch(0.16 0.02 255);
      --color-positive: oklch(0.76 0.14 145);
      --color-attention: oklch(0.78 0.14 68);
      --color-shadow: oklch(0 0 0 / 0.42);
    }
  }

  body {
    background:
      radial-gradient(circle at 10% 5%, color-mix(in oklch, var(--color-primary) 16%, transparent), transparent 28rem),
      radial-gradient(circle at 92% 25%, color-mix(in oklch, var(--color-secondary) 12%, transparent), transparent 30rem),
      var(--color-background);
    color: var(--color-text);
    font-family: var(--font-sans);
    font-size: var(--size-base);
    line-height: 1.65;
  }

  a {
    color: inherit;
  }

  :where(a, button, input):focus-visible {
    outline: 0.2rem solid var(--color-secondary);
    outline-offset: 0.2rem;
  }

  h1 {
    max-width: 19ch;
    margin: var(--space-sm) 0;
    font-size: var(--size-heading-lg);
    line-height: 1.05;
    letter-spacing: -0.04em;
    text-wrap: balance;
  }
}

@layer layout {
  .page-shell {
    width: min(calc(100% - 2rem), var(--max-width));
    margin-inline: auto;
    padding-bottom: 3rem;
  }

  main {
    display: grid;
    gap: var(--space-lg);
    margin-top: var(--space-lg);
  }

  .progress-grid,
  .architecture-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
    gap: var(--space-md);
  }

  .dashboard-frame {
    display: grid;
    grid-template-columns: minmax(8.5rem, 9.5rem) minmax(0, 1fr) minmax(11rem, 14.5rem);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "rail header header"
      "rail main context"
      "rail footer footer";
    gap: var(--space-sm);
    min-height: min(48rem, 100dvh);

    .frame-rail { grid-area: rail; }
    .frame-header { grid-area: header; }
    .frame-main { grid-area: main; }
    .frame-context { grid-area: context; }
    .frame-footer { grid-area: footer; }
  }

  .market-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-rows: minmax(9rem, auto);
    grid-auto-flow: dense;
    gap: var(--space-sm);
  }

  @media (max-width: 66rem) {
    .dashboard-frame {
      min-height: auto;
      grid-template-columns: 1fr;
      grid-template-areas: "header" "rail" "main" "context" "footer";
    }

    .frame-rail nav {
      grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
    }
  }

  @media (max-width: 48rem) {
    .market-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }

  @media (max-width: 38rem) {
    .market-grid {
      grid-template-columns: 1fr;
    }
  }
}

@layer components {
  .skip-link {
    position: fixed;
    z-index: 20;
    left: var(--space-md);
    top: var(--space-md);
    transform: translateY(-200%);
    padding: var(--space-sm) var(--space-md);
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-weight: 900;

    &:focus {
      transform: translateY(0);
    }
  }

  .token-hero {
    padding: clamp(1.5rem, 1rem + 2.5vw, 3.5rem);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: linear-gradient(135deg, color-mix(in oklch, var(--color-primary) 12%, transparent), transparent 50%), var(--color-surface);
    box-shadow: 0 1rem 2.5rem var(--color-shadow);

    > p:last-child {
      max-width: 65ch;
      color: var(--color-text-muted);
      font-size: clamp(1.05rem, 0.98rem + 0.35vw, 1.25rem);
    }

    code {
      color: var(--color-secondary);
      font-family: var(--font-mono);
    }
  }

  .eyebrow {
    margin: 0;
    color: var(--color-secondary);
    font-family: var(--font-mono);
    font-size: 0.85rem;
    font-weight: 900;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .token-section {
    min-width: 0;
    padding: clamp(1rem, 0.75rem + 1.25vw, 2rem);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    box-shadow: 0 0.75rem 2rem var(--color-shadow);
  }

  .section-heading {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-md);
    align-items: start;
    margin-bottom: var(--space-lg);

    > span {
      display: grid;
      place-items: center;
      width: 2.75rem;
      aspect-ratio: 1;
      border-radius: 50%;
      background: var(--color-primary);
      color: var(--color-on-primary);
      font-family: var(--font-mono);
      font-weight: 900;
    }

    h2 {
      margin: 0;
      font-size: var(--size-heading-md);
      line-height: 1.15;
    }

    p {
      margin: var(--space-xs) 0 0;
      color: var(--color-text-muted);
    }
  }

  :is(.progress-card, .architecture-card) {
    min-width: 0;
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface-elevated);

    code {
      display: inline-block;
      margin-bottom: var(--space-xs);
      color: var(--color-secondary);
      font-family: var(--font-mono);
      font-weight: 800;
    }

    h3 {
      margin: 0 0 var(--space-xs);
    }

    p {
      margin: 0;
      color: var(--color-text-muted);
    }
  }

  .progress-card {
    &.progress-card--current {
      border-color: var(--color-primary);
      background: linear-gradient(135deg, color-mix(in oklch, var(--color-primary) 13%, transparent), transparent 55%), var(--color-surface-elevated);
      box-shadow: inset 0.28rem 0 var(--color-primary);
    }
  }

  pre {
    overflow-x: auto;
    margin: var(--space-lg) 0 0;
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: color-mix(in oklch, var(--color-background) 80%, black);
    color: var(--color-text);
    font: 0.9rem/1.7 var(--font-mono);
  }

  .checklist {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 23rem), 1fr));
    gap: var(--space-sm);
    padding: 0;
    list-style: none;

    li {
      position: relative;
      min-width: 0;
      padding: var(--space-md) var(--space-md) var(--space-md) 3rem;
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
      background: var(--color-surface-elevated);

      &::before {
        content: "✓";
        position: absolute;
        left: var(--space-md);
        color: var(--color-positive);
        font-weight: 900;
      }
    }

    code {
      color: var(--color-secondary);
      font-family: var(--font-mono);
    }
  }

  .resiliency-note {
    margin-top: var(--space-md);
    padding: var(--space-md);
    border-left: 0.3rem solid var(--color-primary);
    background: var(--color-surface-elevated);

    p {
      margin-bottom: 0;
      color: var(--color-text-muted);
    }
  }

  footer {
    padding: var(--space-lg) 0;
    color: var(--color-text-muted);
    text-align: center;
    font-family: var(--font-mono);
  }

  .dashboard-frame {
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background:
      linear-gradient(135deg, color-mix(in oklch, var(--color-primary) 10%, transparent), transparent 55%),
      var(--color-surface-elevated);
  }

  :is(.frame-rail, .frame-header, .frame-main, .frame-context, .frame-footer) {
    min-width: 0;
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: color-mix(in oklch, var(--color-surface) 90%, transparent);
  }

  .frame-rail {
    strong {
      display: grid;
      place-items: center;
      width: 3rem;
      aspect-ratio: 1;
      margin-bottom: var(--space-md);
      border-radius: var(--radius-sm);
      background: var(--color-primary);
      color: var(--color-on-primary);
      font-family: var(--font-mono);
    }

    nav {
      display: grid;
      gap: var(--space-xs);
    }

    a {
      display: block;
      width: 100%;
      padding: var(--space-xs) var(--space-sm);
      border: 1px solid transparent;
      border-radius: var(--radius-sm);
      background: color-mix(in oklch, var(--color-surface-elevated) 72%, transparent);
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.78rem;
      font-weight: 800;
      text-decoration: none;

      &:focus-visible,
      &:hover {
        border-color: var(--color-primary);
        background: color-mix(in oklch, var(--color-primary) 16%, var(--color-surface));
        color: var(--color-text);
      }
    }
  }

  .frame-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-md);

    p {
      margin: 0;
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-weight: 800;
    }

    form {
      display: flex;
      align-items: center;
      gap: var(--space-sm);
    }

    label {
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.78rem;
      font-weight: 800;
      text-transform: uppercase;
    }

    input {
      max-width: 13rem;
      padding: var(--space-xs) var(--space-sm);
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
      background: var(--color-background);
      color: var(--color-text);
      font: inherit;
    }
  }

  .frame-footer p {
    margin: 0;
    color: var(--color-text-muted);
    font-family: var(--font-mono);
    font-weight: 800;
  }

  .frame-kicker {
    color: var(--color-secondary) !important;
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .frame-context {
    h2 {
      margin: var(--space-xs) 0;
      font-size: var(--size-heading-md);
      line-height: 1.15;
    }

    > p:not(.frame-kicker) {
      margin: 0;
      color: var(--color-text-muted);
    }
  }

  .context-list {
    display: grid;
    gap: var(--space-xs);
    margin: var(--space-md) 0 0;
    padding: 0;
    list-style: none;

    li {
      padding: var(--space-xs) var(--space-sm);
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.78rem;
    }
  }

  .market-card {
    min-width: 0;
    overflow: hidden;
    padding: var(--space-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface-elevated);

    &.market-card--hero {
      grid-column: span 2;
      grid-row: span 2;
      display: grid;
      align-content: space-between;
      gap: var(--space-md);
      background: linear-gradient(145deg, color-mix(in oklch, var(--color-secondary) 12%, transparent), transparent 50%), var(--color-surface-elevated);
    }

    &.market-card--alert {
      border-color: color-mix(in oklch, var(--color-attention) 70%, var(--color-border));

      > p:last-child {
        margin: 0;
        color: var(--color-text-muted);
      }
    }

    .market-card__heading {
      display: flex;
      align-items: start;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: var(--space-sm);
    }

    .market-card__eyebrow {
      margin: 0 0 var(--space-xs);
      color: var(--color-secondary);
      font-family: var(--font-mono);
      font-size: 0.72rem;
      font-weight: 900;
      letter-spacing: 0.07em;
      text-transform: uppercase;
    }

    h2,
    h3 {
      margin: 0;
      line-height: 1.15;
    }

    h2 {
      font-size: var(--size-heading-md);
    }

    h3 {
      font-size: clamp(1.05rem, 0.97rem + 0.4vw, 1.3rem);
    }

    .market-card__status {
      padding: 0.25rem 0.5rem;
      border: 1px solid var(--color-border);
      border-radius: 999px;
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.68rem;
      font-weight: 800;
      text-transform: uppercase;
    }

    .market-card__lead {
      margin: 0;
      color: var(--color-text-muted);
    }
  }

  .market-chart {
    display: flex;
    align-items: end;
    gap: var(--space-xs);
    min-height: 8.5rem;
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: color-mix(in oklch, var(--color-background) 72%, transparent);

    span {
      flex: 1;
      min-width: 0.35rem;
      height: var(--bar-size);
      border-radius: 0.25rem 0.25rem 0 0;
      background: linear-gradient(180deg, var(--color-secondary), var(--color-primary));
    }
  }

  .market-metrics {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-xs);
    margin: 0;

    div {
      min-width: 0;
      padding: var(--space-xs);
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
    }

    dt {
      color: var(--color-text-muted);
      font-family: var(--font-mono);
      font-size: 0.68rem;
      text-transform: uppercase;
    }

    dd {
      margin: 0.2rem 0 0;
      font-weight: 800;
    }
  }

  .market-list {
    display: grid;
    gap: var(--space-xs);
    margin: var(--space-md) 0 0;
    padding: 0;
    list-style: none;

    li {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--space-sm);
      padding-block: var(--space-xs);
      border-bottom: 1px solid var(--color-border);

      &:last-child {
        border-bottom: 0;
      }
    }

    strong {
      color: var(--color-positive);
      font-family: var(--font-mono);
      font-size: 0.72rem;
    }
  }

  .allocation-bars {
    display: grid;
    gap: var(--space-sm);
    margin-top: var(--space-md);

    span {
      position: relative;
      display: block;
      overflow: hidden;
      padding: 0.35rem var(--space-xs);
      border: 1px solid var(--color-border);
      border-radius: var(--radius-sm);
      color: var(--color-text);
      font-family: var(--font-mono);
      font-size: 0.72rem;
      isolation: isolate;

      &::before {
        content: "";
        position: absolute;
        inset: 0 auto 0 0;
        z-index: -1;
        width: var(--allocation);
        background: color-mix(in oklch, var(--color-primary) 26%, transparent);
      }
    }
  }

  .comparison-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    margin-top: var(--space-xs);
    padding-block: var(--space-xs);
    border-bottom: 1px solid var(--color-border);
    color: var(--color-text-muted);

    &:last-child {
      border-bottom: 0;
    }

    strong {
      color: var(--color-positive);
      font-family: var(--font-mono);
      font-size: 0.72rem;
    }
  }


  /* Week 06: component-level responsiveness. The slot owns the query context;
     the reusable card never inspects the viewport for its internal orientation. */
  .component-placement-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-md);
    margin-top: var(--space-md);
  }

  .component-slot {
    container: market-card-slot / inline-size;
    min-width: 0;
  }

  .adaptive-market-card {
    display: flex;
    flex-direction: column;
    gap: clamp(0.7rem, 3cqw, 1.15rem);
    min-width: 0;
    padding: clamp(0.8rem, 4cqw, 1.35rem);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background:
      linear-gradient(145deg, color-mix(in oklch, var(--color-secondary) 9%, transparent), transparent 54%),
      var(--color-surface-elevated);
  }

  .adaptive-market-card__visual {
    flex: 0 0 auto;
    min-height: 8rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background:
      linear-gradient(135deg, color-mix(in oklch, var(--color-primary) 18%, transparent), transparent 58%),
      repeating-linear-gradient(90deg, transparent 0 12%, color-mix(in oklch, var(--color-border) 45%, transparent) 12% 13%),
      var(--color-background);
    display: flex;
    align-items: end;
    gap: clamp(0.25rem, 1.5cqw, 0.55rem);
    padding: clamp(0.55rem, 2.5cqw, 0.9rem);
  }

  .adaptive-market-card__visual span {
    flex: 1;
    min-width: 0.3rem;
    height: var(--bar-size);
    background: linear-gradient(180deg, var(--color-secondary), var(--color-primary));
  }

  .adaptive-market-card__content {
    min-width: 0;
  }

  .adaptive-market-card__eyebrow {
    margin: 0 0 var(--space-xs);
    color: var(--color-secondary);
    font-family: var(--font-mono);
    font-size: clamp(0.68rem, 2.5cqw, 0.78rem);
    font-weight: 900;
    letter-spacing: 0.07em;
    text-transform: uppercase;
  }

  .adaptive-market-card h3 {
    margin: 0;
    font-size: clamp(1.05rem, 5cqw, 1.55rem);
    line-height: 1.12;
  }

  .adaptive-market-card p:last-child {
    margin: var(--space-xs) 0 0;
    color: var(--color-text-muted);
  }

  @container market-card-slot (min-width: 500px) {
    .adaptive-market-card {
      flex-direction: row;
      align-items: center;
    }

    .adaptive-market-card__visual {
      flex-basis: min(42%, 15rem);
      align-self: stretch;
      min-height: 10rem;
    }

    .adaptive-market-card__content {
      flex: 1;
    }
  }

  @media (max-width: 48rem) {
    .market-card.market-card--hero {
      grid-column: span 2;
    }
  }

  @media (max-width: 38rem) {
    .section-heading {
      grid-template-columns: 1fr;
    }

    .frame-header,
    .frame-header form {
      align-items: stretch;
      flex-direction: column;
    }

    .frame-header input {
      width: 100%;
      max-width: none;
    }

    .market-card.market-card--hero {
      grid-column: auto;
      grid-row: auto;
    }

    .market-metrics {
      grid-template-columns: 1fr;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  @layer base {
    html {
      scroll-behavior: auto;
    }
  }

  @layer reset {
    *, *::before, *::after {
      transition-duration: 0.01ms !important;
    }
  }
}
Actual Week 06 output

One reusable market brief, two simultaneous layouts.

The wide placement becomes horizontal while the narrow drawer placement remains stacked, even though both are shown at the same viewport width.

Wide workspace placement

Main workspace

Context-aware market brief

At 500px or wider the component becomes horizontal.

Narrow drawer placement

Context drawer

Context-aware market brief

Below 500px the same component remains stacked.

03

Part 3: Co-Piloting with AI (Prompts)

AI can help isolate the component-query rules while the human preserves project history, placement semantics, and verification boundaries.

AI assistance allowed

Draft container-query syntax, identify parent slots, and refactor reusable card internals away from media-query dependence.

Human responsibility

Preserve Week 05, use the technical blueprint's 500px implementation threshold, keep page-level media queries where appropriate, and verify both placements and themes.

Prompt 1 · Writing Container Queries
Act as a senior CSS component engineer. I have a reusable card element called .card containing an image and some text, and I want to convert its internal responsiveness from Media Queries to CSS Container Queries.

Implementation requirements:

1. Preserve one reusable HTML card structure with an image region and a text region.

2. Establish an inline-size containment context on the card's parent element.

3. Keep the narrow/default card vertically stacked with the image above the text.

4. When the parent container is wider than 450px, use @container to display the card horizontally with the image beside the text.

5. Use nested CSS where it improves component ownership without introducing Sass-only syntax or a build step.

6. Do not use a viewport @media query to control the card's internal flex direction.

Return the HTML structure and the complete component CSS using @container.
Prompt 2 · Refactoring Layouts for Container Queries
Act as a CSS layout refactoring specialist. Analyze the supplied Trading Dashboard HTML and CSS, where reusable cards appear in both the main asymmetric grid and the sidebar/context aside.

Refactoring requirements:

1. Preserve the existing semantic dashboard frame, card content, design tokens, and page-level responsive layout.

2. Identify the direct parent slots that should become inline-size query containers.

3. Add container-type: inline-size or an equivalent named container shorthand to those parent slots.

4. Refactor the reusable card so its narrow internal layout stacks cleanly instead of being squashed in the sidebar.

5. Use @container for the card's internal wide/narrow composition and keep viewport media queries limited to macro page geometry.

6. Explain any existing media-query rule that should remain because it controls the dashboard frame rather than the card's internal alignment.

Return the corrected container-context and reusable-card CSS, followed by a concise explanation of the refactor boundary.
04

Part 4: Verification & Submission Checklist

Week 06 is complete only when the component reacts to its parent, container units remain bounded, themes stay complete, and prior milestones remain untouched.

  • Placement Test

    At one desktop viewport, confirm the main-workspace card is horizontal while the narrow context-drawer copy is stacked.

  • Containment Context

    Confirm both parent slots establish market-card-slot / inline-size.

  • No Card-Alignment Media Dependency

    Confirm no @media rule changes .adaptive-market-card flex-direction.

  • Macro Query Boundary

    Confirm existing viewport queries still control only page/frame/grid geometry.

  • Container Units

    Confirm bounded cqw values scale the component without horizontal overflow.

  • Theme Coverage

    Check Standard, Playful Pop, Raggedy Granite, Glossy Marble, Luminous Midnight, and Gothic Stickerboard in dark and light mode.

  • Archive Preservation

    Open Weeks 02–05 and verify their completed directories were not modified.

00

Week 07: High-Performance Micro-Interactions & CSS Scroll-Driven Animations

The Week 06 dashboard remains intact while native CSS adds restrained interaction feedback, scroll progress, viewport-entry reveals, and a motion-accessibility shutdown path.

What changed

Buttons, links, form controls, cards, and page scrolling now communicate state through transforms, opacity, focus rings, a root-scroll progress indicator, and view timelines—without local JavaScript scroll listeners.

What stayed locked

Weeks 02–06, the semantic command-center frame, asymmetric market workspace, container-aware component behavior, outer width, theme architecture, and static educational data remain preserved.

01

Part 1: Preserving Your Progress (No Overwriting)

Week 07 is created beside Week 06 rather than replacing any completed checkpoint.

  1. Duplicate the approved Week 06 milestone.

    Carry forward the complete container-aware dashboard, local cascade layers, native nesting, semantic frame, asymmetric grid, and themeable token contract.

  2. Replace only the Week 07 placeholder.

    trading-dashboard/week07/ receives its own live page, local stylesheet, and README.

  3. Freeze Weeks 02 through 06.

    Do not back-port the new motion or scroll-timeline rules into historical milestone directories.

  4. Keep the layout static-first.

    Motion may enhance the interface, but unsupported scroll timelines and reduced-motion preferences must never remove required content or controls.

02

Part 2: The Week 07 technical blueprint

The browser drives interaction and scroll progress directly while transforms/opacity avoid layout-driven animation and reduced motion remains authoritative.

Recognize each subject by the problem it solves.

Interaction feedback

Use transitions only on properties that do not require a new layout calculation for every frame; the Week 07 implementation limits movement to transforms and opacity while border/shadow provide restrained depth changes.

Keyboard discoverability

Hover is not a keyboard state. A dedicated :focus-visible ring tied to --accent remains visible whether motion is enabled or reduced.

Scroll progress

scroll(root) maps the document's scroll range onto keyframe progress, removing the need for a scroll event listener that manually calculates width.

Entry reveals

view() maps an individual subject's visibility to keyframe progress. Because current support is not universal, the rule is guarded so unsupported browsers receive the normal static rendering.

Apply the Week 07 requirements step by step.

  1. Expose one semantic accent token.

    Alias the established secondary color as --accent so focus rings remain compatible with every installed style family.

  2. Add pointer/active feedback without layout animation.

    Use small translateY()/scale() transforms and restrained opacity, border, or shadow changes. Do not animate width, height, margin, or positional layout offsets.

  3. Keep focus independent from motion.

    Apply the strong :focus-visible ring outside the motion preference block so keyboard users never lose orientation when Reduce Motion is enabled.

  4. Bind the top progress bar to root scroll.

    Animate transform: scaleX() from zero to one and set animation-timeline: scroll(root).

  5. Bind reveal cards to their own view progress.

    Use view() plus a bounded animation range so content fades/translates during entry rather than remaining invisible until a script observes it.

  6. Gate limited-availability features.

    Place scroll/view timeline declarations inside @supports, leaving the base state statically visible everywhere else.

  7. Honor reduced motion as a full shutdown.

    Disable animation/transition timing and hide the decorative progress bar while preserving focus, layout, and content.

Week 07 CSS · micro-interactions, scroll progress, view reveals
.scroll-progress-bar {
  position: fixed;
  inset: 0 auto auto 0;
  inline-size: 100%;
  block-size: 0.28rem;
  transform: scaleX(0);
  transform-origin: left center;
  background: linear-gradient(90deg, var(--color-primary), var(--accent));
}

:where(a, button, input):focus-visible {
  outline: 0.2rem solid var(--accent);
  outline-offset: 0.22rem;
}

@media (prefers-reduced-motion: no-preference) {
  :where(.frame-rail a, .market-card, .adaptive-market-card, input) {
    transition: transform 180ms ease, opacity 180ms ease, box-shadow 180ms ease;
  }

  @supports (animation-timeline: scroll()) {
    .scroll-progress-bar {
      animation: week07-scroll-progress auto linear both;
      animation-timeline: scroll(root);
    }

    :where(.token-section, .market-card, .adaptive-market-card) {
      animation: week07-view-reveal auto linear both;
      animation-timeline: view();
      animation-range: entry 8% cover 30%;
    }
  }
}

@keyframes week07-scroll-progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

@keyframes week07-view-reveal {
  from { opacity: 0; transform: translateY(20px) scale(0.985); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-delay: -1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0s !important;
    transition-delay: 0s !important;
  }
}
Actual Week 07 output

One preserved dashboard, three layers of CSS-only feedback.

The live milestone keeps Week 06's container-aware market brief, adds keyboard/pointer micro-interactions, places a root-scroll progress indicator at the top edge, and reveals content with native view timelines when supported.

Focus / Hovertransform · opacity · accent ring
Scroll ProgressscaleX() · scroll(root)
View Revealopacity · translateY() · view()
Reduced Motionstatic layout · focus preserved
Progressive-enhancement note: current MDN documentation marks animation-timeline, scroll(), and view() as limited availability. The Week 07 base state therefore never depends on those features for content visibility or interaction.
03

Part 3: Co-Piloting with AI (Prompts)

AI can draft keyframes and interaction rules, while the human owns accessibility, performance boundaries, archive preservation, and cross-theme verification.

AI assistance allowed

Draft transform/opacity hover states, focus-visible ring examples, root scroll progress syntax, view-timeline ranges, and reduced-motion reset rules.

Human responsibility

Keep Week 06 untouched, reject layout-triggering animation, verify keyboard focus, confirm reduced-motion behavior, and ensure limited-availability features degrade to a readable static interface.

Prompt 1 · Designing High-Performance Hover States
I have a card component called .card. I want to design a subtle micro-interaction when a user hovers or tabs onto it.

Requirements:

1. Scale the card up very slightly to 1.02x.
2. Add a clean, restrained shadow without changing layout dimensions.
3. Prefer transform and opacity for movement so the interaction is hardware-friendly.
4. Do not animate width, height, margin, top, left, or other layout-triggering geometry.
5. Include a clearly visible, high-contrast :focus-visible ring using the page's --accent token.
6. Ensure the focus treatment remains available even when motion is disabled.

Return the CSS and briefly explain why the selected animated properties are appropriate.
Prompt 2 · Building CSS Scroll-Driven View Animations
I want to create a scroll-reveal animation for my Trading Dashboard cards using native modern CSS scroll-driven animations.

Requirements:

1. Each card should fade from opacity 0 to 1 as it enters the viewport.
2. Each card should translate upward by 20px and settle at its normal position.
3. Use animation-timeline: view() rather than a JavaScript scroll listener or IntersectionObserver.
4. Explain how the view-progress timeline bounds are determined by the subject's visibility in its scroll container.
5. Include a practical animation-range so the reveal finishes early enough for comfortable reading.
6. Add progressive enhancement so unsupported browsers keep the card statically visible.
7. Add prefers-reduced-motion handling that removes the movement without removing the card or its keyboard focus treatment.

Return the complete CSS and a concise explanation of the timeline and fallback behavior.
04

Part 4: Verification & Submission Checklist

Week 07 is complete only when motion remains optional, focus remains visible, scroll effects require no local JavaScript, and prior milestones stay untouched.

  • Reduced Motion Test

    Enable Reduce Motion at the OS level, refresh, and confirm animations/transitions shut down while the static dashboard remains fully usable.

  • Keyboard Friendly

    Navigate with Tab only and confirm links, controls, and theme/navigation interactions show an obvious focus-visible state.

  • Interaction Properties

    Inspect Week 07 hover/active rules and confirm they avoid animated width, height, margin, and positional layout offsets.

  • Root Scroll Timeline

    In a supporting browser, confirm the top progress bar advances with animation-timeline: scroll(root).

  • View Timeline

    Confirm cards reveal with view(); disable timeline support and verify those cards remain statically visible.

  • No JS Scroll Observer

    Confirm Week 07 introduces no local JavaScript, scroll event listener, or IntersectionObserver.

  • Paint Flashing

    Use Chrome DevTools Rendering → Paint Flashing and confirm pointer interaction does not cause broad page repainting from layout animation.

  • Theme Coverage

    Check all seven style families—including Baroque Plexiglas—in dark and light mode, at desktop and narrow widths.

  • Archive Preservation

    Open Weeks 02–06 and verify their completed directories were not modified.