=== StoryPress ===

Contributors: bikram_sth
Tags: news, blog, one-column, two-columns, right-sidebar, left-sidebar, custom-colors, custom-logo, custom-header, custom-background, custom-menu, featured-images, threaded-comments, block-patterns, translation-ready, rtl-language-support
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.0.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

An accessible news and magazine theme with eight switchable homepage layouts.

== Description ==

StoryPress is an editorially-minded news and magazine theme. Editors can
switch the homepage between eight layouts from the Customizer — no page
builder or plugin required:

* **Grid** — equal-weight story cards, good for a general news front page.
* **List** — compact rows with a thumbnail and summary, good for a busy
  wire-style feed.
* **Magazine** — one large lead story followed by a grid of secondary
  stories, good for a features/magazine front page.
* **Hero Grid** — a full-bleed hero photo with an overlaid headline,
  followed by a four-column grid of secondary stories.
* **Traditional Wire** — a dense, text-forward headline feed with no
  thumbnails, styled after classic wire-service listings.
* **Top Stories** — an asymmetric mixed-size grid: one large lead story,
  two medium stories, then a row of smaller ones, sized entirely with CSS.
* **Latest News (Horizontal)** — a horizontally scrolling strip of
  headline cards, good for a "latest" ticker section.
* **Latest News (Vertical)** — a dense, timestamped single-column feed
  with no thumbnails, good for a live-blog-style front page.

Additional Customizer controls: accent color, sidebar position (left,
right, or none), custom footer text, a custom logo, an optional masthead
header image, a custom background, social media icon links (Facebook,
X/Twitter, Instagram, YouTube, LinkedIn), and up to three optional
category-based homepage sections (extra story rows pulling from a chosen
category, shown below the main layout). StoryPress also ships four
custom block styles (Pull Quote, Dotted separator, Outline button,
Caption Card image) and two starter block patterns (Story Byline, Pull
Quote Section) under their own "StoryPress" pattern category, plus
editor styles so the block editor matches the front end and support for
the Gallery, Video, and Quote post formats.

Every single post automatically gets an auto-generated table of contents
(when there are three or more headings), an estimated reading time, an
"About the author" box, and up to three related stories from shared
categories — sticky posts get a "Featured" badge wherever they appear.
Editors can also add three optional footer widget areas. Readers get an
optional dark mode and a three-step text-size control, both in the
header and both remembered locally between visits.

The primary
navigation supports multi-level dropdowns built on the WAI-ARIA
Disclosure pattern, is fully operable by keyboard (Tab, Shift+Tab,
Escape, click-outside-to-close), and every image, empty state, and
default layout has real CSS — nothing is left unstyled.

== Installation ==

1. In your admin panel, go to Appearance > Themes and click the Add New button.
2. Click Upload Theme and Choose File, then select the theme's .zip file. Click Install Now.
3. Click Activate to use your new theme right away.
4. Go to Appearance > Customize to choose a homepage layout, accent color, and sidebar position.

== Frequently Asked Questions ==

= Does this theme support any plugins? =

StoryPress implements only core WordPress theme APIs (menus, widgets,
the Customizer, post formats via core markup). It does not register any
custom post types, blocks, shortcodes, or user roles, so it works
predictably alongside any content plugin without territorial conflicts.

= Does StoryPress add SEO/social sharing tags? =

No. Open Graph tags, Twitter Cards, and structured data (Schema.org/
JSON-LD) are intentionally left to a dedicated SEO or structured-data
plugin, so you can choose and control that independently of your theme.
StoryPress itself sticks to layout, typography, and navigation.

= What are the homepage category sections? =

Go to Appearance > Customize > Homepage Category Sections to add up to
three extra story rows below your main homepage layout, each pulling a
configurable number of posts from a category you choose. Useful for a
"World" or "Sport" strip beneath your main front-page layout.

= How do I change the homepage layout? =

Go to Appearance > Customize > Homepage Layout and choose from Grid, List,
Magazine, Hero Grid, Traditional Wire, Top Stories, Latest News
(Horizontal), or Latest News (Vertical). The change applies immediately to
the homepage only; single posts, pages, and archives use a consistent
list-style layout.

= What are the dark mode and text-size controls? =

Two small controls in the header, next to the social icons. Dark mode
toggles a dark color scheme; the text-size control has three steps
(smaller, default, larger). Both choices are remembered in the visitor's
own browser (via localStorage) so they persist on their next visit —
nothing is sent to or stored on the server, and no cookie is set. See
the Privacy section below for exactly what's stored.

= What shows up automatically on a single post? =

A breadcrumb trail (Home > Category > Post Title), a table of contents
(once a post has three or more headings), an estimated reading time, an
"About the author" box using the author's bio from their WordPress
profile (only shown if they've filled one in), and up to three related
stories pulled from the post's own categories (only shown if it has at
least one). A reading progress bar also appears at the top of the
viewport as you scroll. None of this needs to be configured — it
appears automatically when the underlying content (headings, author
bio, categories) is present.

== Privacy ==

StoryPress does not set cookies and does not transmit any data to a
third-party server. It does use localStorage for exactly two optional
reader preferences, both set only when a visitor clicks the theme's
dark-mode or text-size controls: storypressDarkMode ('1' or '0') and
storypressFontSize ('sm' or 'lg', absent for the default size). Both
values never leave the visitor's browser — they're read back by
inc/reader-preferences.php's inline script on the next page load purely
to reapply the same appearance, and are not sent to the site's server or
anywhere else. If localStorage is unavailable (private browsing, disabled
storage, etc.) the preferences simply don't persist between page loads;
nothing breaks.

The theme's Customizer settings (layout choice,
accent color, sidebar position, footer text, category sections) are
stored as standard WordPress theme_mods in the site's own database, the
same as any other WordPress Customizer setting, and are never sent
anywhere else. The optional social media icon links in the header are
plain outbound links (rel="noopener noreferrer") to profile URLs you
provide — StoryPress does not track clicks on them or load anything from
those platforms.

Threaded comments use WordPress core's own comment-cookie functionality
(the "Save my name, email..." checkbox), which is core behavior, not
something this theme adds.

== Resources ==

* Underscores (_s) starter theme, (C) 2012-2023 Automattic, Inc.,
  https://underscores.me/, licensed under GPLv2 or later. StoryPress's
  template file structure and PHP scaffolding are based on this starter.
* Normalize-style base CSS resets in style.css were written from scratch
  for this theme (no third-party reset library bundled).
* No icon fonts, web fonts, or JavaScript libraries are bundled; the
  theme relies solely on system fonts and vanilla JavaScript
  (js/navigation.js, js/customizer.js), both written for this theme.

== Changelog ==

= 1.0.4 =
* Fixed: the mobile menu panel didn't trap focus. Tabbing past the last
  menu item moved focus into the rest of the page instead of back to
  the toggle button, and the same in reverse with Shift+Tab off the
  first item or the toggle button - so keyboard users could tab straight
  out of an open menu without it ever closing. The toggle button and
  the panel's currently-visible focusable items (submenu items inside a
  collapsed submenu are correctly excluded) now form a closed loop:
  Tab off the last item goes to the toggle button, Shift+Tab off the
  toggle button or the first item goes to the other end. Escape now
  also closes the top-level panel (previously it only closed an open
  submenu) and returns focus to the toggle button. None of this affects
  desktop, where the toggle button is hidden and the guard conditions
  make the new listener a no-op.
* Fixed: a long title or a long word in a comment (a long URL, for
  example) with no natural break point could force its container wider
  than the viewport, scrolling the whole page horizontally. Added
  overflow-wrap/word-wrap: break-word to body, which - being an
  inherited property - covers every text container theme-wide (post
  titles in every layout, comment content, the table of contents,
  related posts, everywhere), not just the two places this was
  reported. Also added overflow-x: hidden on html as a safety net
  against any other unanticipated cause of horizontal overflow; the
  pre-block's own overflow-x: auto is unaffected and still scrolls
  long code lines internally as intended.
* Fixed: the "Next Story" navigation card's text wasn't actually
  right-aligned. The outer .post-nav-next { text-align: right; } rule
  had no effect - it's a flex container, and text-align doesn't
  position flex children. The real alignment depended on
  .post-nav-body { align-items: flex-end; } correctly shrinking a
  legacy display: -webkit-box element (used for the 2-line title
  clamp) down to its content width, which browsers don't handle
  consistently. The actual visible symptom was the "Next Story" label
  and arrow icon staying left-anchored, since that row
  (.post-nav-direction) is its own flex row with the browser's default
  justify-content: flex-start, never overridden. Replaced the fragile
  shrink-to-fit approach with justify-content: flex-end on that row;
  children now stay full-width and align internally via
  text-align/justify-content, which works regardless of how any given
  browser sizes the -webkit-box title. Updated the matching mobile and
  RTL overrides to match.
* Fixed: a <pre> block in a comment (e.g. a long pasted code snippet or
  URL) had no CSS at all - only .entry-content pre was styled, not
  .comment-content pre - so it fell back to the browser default
  (overflow: visible, no wrap) and spilled out of its container. The
  overflow-x: hidden safety net added above meant this no longer
  scrolled the whole page, but it did mean the overflow was silently
  clipped and unreadable instead, which is worse. Merged the
  entry-content and comment-content pre/code selectors into one shared
  rule so both get the same overflow-x: auto scroll-within-its-own-box
  treatment, and so this same context can't fall out of sync again in
  the future.

= 1.0.3 =
* Fixed: with a sidebar enabled, the Latest News (Horizontal) layout's
  scrolling strip pushed the sidebar off-screen, only reachable by
  scrolling the whole page horizontally to the end. #primary is a CSS
  Grid item in the has-sidebar layout (grid-template-columns: 2fr 1fr),
  and grid items default to min-width: auto — which lets a child's
  natural, unclipped content width (here, the horizontal-scroll strip's
  flex row of never-shrinking 240px cards) force that track wider than
  its fair share, rather than respecting grid-template-columns and
  scrolling within it. Fixed by setting min-width: 0 on #primary in both
  the default and sidebar-left grid contexts; the strip's own
  overflow-x: auto still makes it scroll normally within the resulting
  correctly-sized column. The no-sidebar (full-width) layout was never
  affected, since #primary there is a normal block element, not a grid
  item, and sizes to its container regardless of content width.
* Fixed: the search form (used on the 404 page, the "no results" empty
  state, and the core Search widget) had no base CSS at all, rendering
  as unstyled browser-default inputs. The existing
  ".error-404 .search-form { justify-content: center; }" rule had
  consequently never actually done anything either, since
  justify-content only affects flex/grid containers and .search-form
  had no display: flex declared anywhere. Added real styling (rounded
  input with focus ring, pill-shaped submit button) and margin: auto so
  the 404 page's centering actually takes effect.
* Styled category and tag links in the post footer as pill-style chips,
  matching the existing tag-cloud widget's visual language, and styled
  wp_link_pages() output (paginated post/page navigation) to match the
  numbered pagination style used elsewhere.
* Added a branded accent-colored text selection color (::selection) and
  a matching custom scrollbar (both scrollbar-color for Firefox and
  ::-webkit-scrollbar for Chromium/Safari) on the Latest News
  (Horizontal) layout's scroll strip.
* Styled several more previously-unstyled elements: the "Continue
  reading" more-link, the classic [gallery] shortcode grid, comment
  pagination (the_comments_pagination() uses a "comment-navigation"
  wrapper class our pagination CSS never matched, since it only
  targeted "pagination"), general select/text/search widget form
  fields, nested widget lists (Custom Menu submenus, hierarchical
  Categories), and the comment form's required-field asterisk.
* Added a print stylesheet: hides navigation, sidebar, footer, social
  icons, and comment form when printing; reveals link URLs after
  article-body and post-footer links; avoids breaking images, tables,
  and blockquotes across a page boundary.
* Fixed three more leftover hardcoded hex colors (#ccc on comment form
  fields, and two separate #e2e2e2 instances) that should have used
  the --storypress-hairline design token like the rest of the theme.
* Added automatic single-post content: a table of contents (posts with
  3+ headings; storypress_add_table_of_contents() adds the IDs and the
  box in one pass over the_content(), so it can't run the rest of the
  content filters twice), an estimated reading time, an "About the
  author" box (only shown if the author has a bio), and up to three
  related stories by shared category (only shown if the post has at
  least one). Styled all four - previously called but with zero CSS.
* Added a "Featured" badge for sticky posts, shown wherever they appear
  (homepage layouts, category sections, search results). Removed a
  dead, unreachable duplicate storypress_sticky_badge() definition that
  a function_exists() guard had silently made unreachable - the badge
  itself was already working correctly off the first definition, but
  the second was confusing dead code.
* Added post-format support (add_theme_support('post-formats',
  array('gallery','video','quote'))) with a small format badge on
  single posts (storypress_post_format_icon() was already implemented
  and called, but - like the features above - had no CSS).
* Added three optional footer widget areas (Footer 1/2/3), shown in a
  three-column row above the footer credit line when at least one has
  a widget assigned.
* Added an optional dark mode and a three-step text-size control in the
  header. Both preferences save to localStorage
  (storypressDarkMode, storypressFontSize) and are applied via a
  blocking inline script at wp_body_open() - before first paint - so
  there's no flash of the wrong theme on page load. Implementing this
  required splitting the --storypress-ink design token in two:
  --storypress-heading for text/headings/visibility-dependent borders
  (which now correctly turns light under dark mode) and --storypress-ink
  itself, left untouched, for the theme's "filled dark button with
  white text" elements (pagination hover, submit buttons, the calendar
  widget header, etc.), which need to stay dark regardless of theme -
  redefining --storypress-ink globally would have made those buttons'
  hardcoded white text unreadable against their own now-light
  background. Also added a dedicated --storypress-code-bg token so
  <pre> blocks stay dark-on-light regardless of site theme, for the
  same reason. Documented in the Privacy section: both keys, both
  browser-only, both optional.
* Added a visible breadcrumb trail (Home > Category > Post Title, etc.)
  on single posts, pages, archives, and search results - plain on-page
  navigation UI, not structured data, so unrelated to the OG/JSON-LD
  removal above.
* Added a back-to-top button (appears after scrolling ~600px) and a
  reading-progress bar (single posts only). Both share one throttled
  scroll listener (inc/scroll-effects.php, js/scroll-effects.js). The
  back-to-top click handler deliberately omits an explicit "behavior"
  option on scrollTo() so it inherits the page's CSS scroll-behavior
  (smooth, or auto under prefers-reduced-motion) instead of forcing
  smooth scrolling regardless of that preference.
* Added RTL language support: style-rtl.css plus
  wp_style_add_data('storypress-style', 'rtl', true). Named
  style-rtl.css specifically, not rtl.css, because that's the filename
  WordPress core actually computes and requests (inserting "-rtl"
  before ".css" in the main stylesheet's filename) - a differently
  named file would simply never load. Loads alongside style.css, not
  instead of it, so it only needs to contain the rules that don't
  already auto-mirror; most of the theme's flexbox/grid layout mirrors
  automatically per the CSS spec once dir="rtl" is set, so this covers
  what doesn't: floats, physical left/right positioning (skip link,
  submenu flyouts, the featured badge, back-to-top, the progress bar),
  and asymmetric margins/borders/padding (blockquotes, sticky posts,
  comment indentation, alignleft/alignright).

= 1.0.2 =
* Fixed: the mobile menu toggle button never worked. navigation.js looked
  it up with container.querySelector('.menu-toggle'), where container is
  #site-navigation — but the button lives in .site-branding
  .site-header-actions, a sibling of #site-navigation, not a descendant,
  so the lookup always returned null. Fixed by querying the document
  instead of the (wrong) container scope.
* Redesigned the mobile menu: the plain text "Menu" button is now an
  animated hamburger icon that morphs into an X when open (CSS-only,
  respects prefers-reduced-motion), and the dropdown panel is a
  proper card (border, shadow, rounded corners, dividers between items,
  larger 44px+ tap targets) that slides open with a smooth height/opacity
  transition instead of an abrupt display:none/flex swap. Closed-state
  items are still fully removed from the tab order (visibility: hidden,
  applied only after the collapse transition finishes) so keyboard users
  never tab into an invisible menu.
* Fixed: nested submenus rendered squeezed/misshapen on mobile. Every
  <li> uses display: flex (to lay its link and toggle-button side by
  side), which desktop submenus never had to contend with because
  position: absolute removes them from their parent's flex layout
  entirely. Fixed by leaving submenus on position: absolute (inherited
  from the base desktop rule) on mobile too, so they float as dropdown
  cards below their trigger exactly like desktop; mobile only overrides
  min-width/width so the dropdown spans the full menu width, and
  top/left on third-level+ submenus so they drop straight down instead
  of flying out sideways like desktop's hover-flyout does. Also added
  progressively deeper indentation for third-level+ nested items.
* Fixed: the submenu toggle button's aria-label was built in JavaScript
  with a hardcoded English string ('Toggle submenu for ' + label),
  making it untranslatable. Now passed through wp_localize_script() as
  a translatable %s template.
* Fixed: languages/storypress.pot previously contained only headers.
  Regenerated as a complete POT with every real string extracted from
  the source.
* Updated Tested up to from 6.6 to 7.0, the current WordPress stable
  release.
* Removed an unused wp_style_add_data(..., 'rtl', 'replace') hint —
  no rtl.css ships with the theme.
* Removed the accessibility-ready tag. An accessibility-ready review is
  a separate WordPress.org process with its own timeline; the tag can be
  re-added later if that review is specifically requested and completed.
* Removed Open Graph, Twitter Card, and Schema.org/JSON-LD structured
  data output (storypress_output_meta_tags(),
  storypress_output_structured_data(), storypress_structured_data(), and
  the inc/seo.php file that contained them) per WordPress.org reviewer
  feedback: this is plugin territory, not something a theme should
  implement, since it should be manageable independently of whichever
  theme is active. Site owners who want this should use a dedicated SEO
  or structured-data plugin.
* Replaced core's plain-text the_post_navigation() on single posts with
  a custom card-based previous/next navigation (storypress_post_navigation()
  in inc/template-tags.php): thumbnail, directional label, and title in a
  bordered card with hover lift, two columns on desktop and stacked on
  mobile.
* Styled several previously-unstyled elements: blockquotes (accent
  left border, serif italic, optional cite), archive/search page headers,
  entry-content lists/hr/code/pre/tables, and comment author avatars
  (44px, requested at that size via wp_list_comments() rather than
  upscaled from the 32px default, so they stay sharp).
* Fixed a leftover hardcoded hex color (#e2e2e2) in the comment-list
  border that should have used the --storypress-hairline token like
  the rest of the theme.

= 1.0.0 =
* Initial release.
* Eight Customizer-selectable homepage layouts: Grid, List, Magazine,
  Hero Grid, Traditional Wire, Top Stories (asymmetric grid), and Latest
  News in both horizontal-scroll and vertical-feed forms.
* Optional homepage Category Sections: up to three Customizer-configurable
  extra story rows, each backed by its own category-filtered query, shown
  below the main homepage layout.
* Accessible primary navigation: WAI-ARIA Disclosure pattern submenus,
  aria-expanded kept in sync via a combined "toggled" (click) and "focus"
  (keyboard) state, Escape-to-close, click-outside-to-close, and a custom
  nav walker that restores both aria-current="page" and the
  menu-item-has-children class WordPress core normally adds automatically.
* Skip link implemented as a self-contained, explicitly-colored
  .skip-link / .skip-link:focus pair, fixed-positioned above any sticky
  header.
* Customizer controls: accent color, sidebar position (left/right/none),
  footer text, custom logo, optional masthead header image, custom
  background, and social media profile links (Facebook, X/Twitter,
  Instagram, YouTube, LinkedIn) shown next to the logo as inline SVG
  icons — no icon font, no external/CDN request.
* Customizer-driven CSS (accent color) is injected with
  wp_add_inline_style() on the storypress-style handle at priority 11 —
  no raw <style> tag is echoed in wp_head.
* Block-editor support: add_theme_support( 'wp-block-styles' ) and
  add_theme_support( 'align-wide' ), add_theme_support( 'editor-styles' )
  with a matching editor-style.css, four custom block styles (Pull Quote,
  Dotted separator, Outline button, Caption Card image), and two starter
  block patterns (Story Byline, Pull Quote Section) under a dedicated
  "StoryPress" pattern category.
* Recommended core CSS classes implemented with real styling: .sticky,
  .gallery-caption, .bypostauthor, .alignleft, .alignright, .aligncenter,
  .alignwide, .alignfull.
* Global img { max-width: 100%; height: auto; } reset, plus explicit CSS
  for every place a thumbnail can render across every layout, single
  posts, pages, and archive/search results.
* wp_nav_menu() fallback_cb renders a real wp_list_pages()-based menu
  when no menu is assigned, so a fresh install never shows an empty nav.
* No custom post types, blocks, shortcodes, or roles — only core
  WordPress theme APIs.

== License ==

StoryPress WordPress Theme, Copyright 2026 Bikram
StoryPress is distributed under the terms of the GNU GPL, version 2 or later.

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.

You should have received a copy of the GNU General Public License along
with this program. If not, see https://www.gnu.org/licenses/gpl-2.0.html.

StoryPress bundles no third-party code beyond the Underscores (_s)
starter-theme scaffolding credited in the Resources section above, which
is itself GPLv2-or-later licensed.
