This commit is contained in:
Nick 2025-06-06 14:14:35 +01:00
parent c06911e129
commit 8f2a5f38bc
328 changed files with 2685 additions and 22643 deletions

View File

@ -8,6 +8,38 @@
<ItemGroup> <ItemGroup>
<Content Remove="bundleconfig.json" /> <Content Remove="bundleconfig.json" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-grid.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-grid.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-grid.min.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-grid.min.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-grid.rtl.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-grid.rtl.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-grid.rtl.min.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-grid.rtl.min.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-reboot.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-reboot.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-reboot.min.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-reboot.min.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-reboot.rtl.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-reboot.rtl.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-reboot.rtl.min.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-reboot.rtl.min.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-utilities.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-utilities.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-utilities.min.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-utilities.min.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-utilities.rtl.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-utilities.rtl.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-utilities.rtl.min.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap-utilities.rtl.min.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap.min.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap.min.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap.rtl.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap.rtl.css.map" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap.rtl.min.css" />
<Content Remove="C:\Users\Nick\.nuget\packages\bootstrap\5.3.3\contentFiles\any\any\wwwroot\css\bootstrap.rtl.min.css.map" />
<Content Update="web.config"> <Content Update="web.config">
<CopyToPublishDirectory>Never</CopyToPublishDirectory> <CopyToPublishDirectory>Never</CopyToPublishDirectory>
</Content> </Content>
@ -21,16 +53,16 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="bootstrap" Version="5.3.3" /> <PackageReference Include="bootstrap" Version="5.3.3" />
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" /> <PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageReference Include="Microsoft.Web.Administration" Version="11.1.0" /> <PackageReference Include="Microsoft.Web.Administration" Version="11.1.0" />
<PackageReference Include="SendGrid" Version="9.29.3" /> <PackageReference Include="SendGrid" Version="9.29.3" />
<PackageReference Include="SixLabors.Fonts" Version="2.0.6" /> <PackageReference Include="SixLabors.Fonts" Version="2.1.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" /> <PackageReference Include="SixLabors.ImageSharp" Version="3.1.8" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.4" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.6" />
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.3" /> <PackageReference Include="SixLabors.ImageSharp.Web" Version="3.1.5" />
<PackageReference Include="System.Drawing.Common" Version="9.0.0" /> <PackageReference Include="System.Drawing.Common" Version="9.0.5" />
<PackageReference Include="System.Net.Http" Version="4.3.4" /> <PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="WebMarkupMin.AspNetCoreLatest" Version="2.18.0" /> <PackageReference Include="WebMarkupMin.AspNetCoreLatest" Version="2.19.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,124 @@
using CatherineLynwood.Controllers;
using CatherineLynwood.Models;
using CatherineLynwood.Services;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
public class AccessController : Controller
{
#region Private Fields
private readonly IAccessCodeService _accessCodeService;
private readonly ILogger<HomeController> _logger;
private DataAccess _dataAccess;
#endregion Private Fields
#region Public Constructors
public AccessController(ILogger<HomeController> logger, DataAccess dataAccess, IAccessCodeService accessCodeService)
{
_logger = logger;
_dataAccess = dataAccess;
_accessCodeService = accessCodeService;
}
#endregion Public Constructors
#region Public Methods
[HttpGet]
public IActionResult MailingList()
{
return View();
}
[HttpPost]
public async Task<IActionResult> MailingList(Marketing marketing)
{
bool success = true;
if (!string.IsNullOrEmpty(marketing.Email))
{
success = await _dataAccess.AddMarketingAsync(marketing);
}
if (success)
{
// Set cookie so we dont ask again
Response.Cookies.Append("MailingListPrompted", "true", new CookieOptions
{
Expires = DateTimeOffset.UtcNow.AddYears(5),
IsEssential = true
});
// Redirect back to original destination
var returnUrl = TempData["ReturnUrl"] as string ?? "/Extras";
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Prompt");
}
}
[HttpPost]
public IActionResult Decline()
{
// Set cookie so we dont ask again
Response.Cookies.Append("MailingListPrompted", "true", new CookieOptions
{
Expires = DateTimeOffset.UtcNow.AddYears(5),
IsEssential = true
});
// Redirect back to original destination
var returnUrl = TempData["ReturnUrl"] as string ?? "/Extras";
return Redirect(returnUrl);
}
[HttpGet]
public async Task<IActionResult> Prompt(string returnUrl = "/Extras")
{
var (pageNumber, wordIndex) = await _accessCodeService.GetCurrentChallengeAsync();
ViewBag.PageNumber = pageNumber;
ViewBag.WordIndex = wordIndex;
ViewBag.ReturnUrl = returnUrl;
return View();
}
[HttpPost]
public async Task<IActionResult> Prompt(string userWord, string returnUrl = "/Extras")
{
var (accessLevel, highestBook) = await _accessCodeService.ValidateWordAsync(userWord);
if (accessLevel > 0 && highestBook > 0)
{
HttpContext.Session.SetInt32("BookAccessLevel", accessLevel);
HttpContext.Session.SetInt32("BookAccessMax", highestBook);
var promptedCookie = Request.Cookies["MailingListPrompted"];
if (string.IsNullOrEmpty(promptedCookie))
{
TempData["ReturnUrl"] = returnUrl;
return RedirectToAction("MailingList");
}
return Redirect(returnUrl);
}
var (pageNumber, wordIndex) = await _accessCodeService.GetCurrentChallengeAsync();
ViewBag.PageNumber = pageNumber;
ViewBag.WordIndex = wordIndex;
ViewBag.ReturnUrl = returnUrl;
ViewBag.Error = "Invalid word. Please try again.";
return View();
}
#endregion Public Methods
}

View File

@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Mvc;
namespace CatherineLynwood.Controllers
{
[Route("the-alpha-flame/extras/discovery")]
public class DiscoveryController : Controller
{
public IActionResult Index()
{
return View();
}
[Route("epilogue")]
public IActionResult Epilogue()
{
return View();
}
[Route("scrap-book")]
public IActionResult ScrapBook()
{
return View();
}
[Route("maggies-designs")]
public IActionResult MaggiesDesigns()
{
return View();
}
}
}

View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
namespace CatherineLynwood.Controllers
{
public class ErrorController : Controller
{
public IActionResult AccessDenied()
{
return View();
}
}
}

View File

@ -66,12 +66,6 @@ namespace CatherineLynwood.Controllers
return View(contact); return View(contact);
} }
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[Route("feed.xml")] [Route("feed.xml")]
[Route("rss.xml")] [Route("rss.xml")]
[Route("rss")] [Route("rss")]
@ -131,30 +125,12 @@ namespace CatherineLynwood.Controllers
return File(rssBytes, "application/rss+xml", "rss.xml"); return File(rssBytes, "application/rss+xml", "rss.xml");
} }
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
// Helper method to get the file size in bytes
private long GetFileSizeInBytes(string imageUrl)
{ {
string filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", imageUrl.TrimStart('/').Replace("/","\\")); return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
FileInfo fileInfo = new FileInfo(filePath);
return fileInfo.Exists ? fileInfo.Length : 0;
} }
// Helper method to convert the original image URL to a 400px JPEG URL in the "jpg" folder
private string ConvertToJpgUrl(string originalFileName)
{
// Get the filename without the extension
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(originalFileName);
// Construct the full URL for the 400px JPEG in the "jpg" folder
string jpgUrl = $"images/jpg/{fileNameWithoutExtension}-400.jpg";
return jpgUrl;
}
public async Task<IActionResult> Index() public async Task<IActionResult> Index()
{ {
//await SendEmail.Execute(); //await SendEmail.Execute();
@ -173,6 +149,32 @@ namespace CatherineLynwood.Controllers
return View(); return View();
} }
[Route("privacy")]
public IActionResult Privacy()
{
return View();
}
// Helper method to convert the original image URL to a 400px JPEG URL in the "jpg" folder
private string ConvertToJpgUrl(string originalFileName)
{
// Get the filename without the extension
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(originalFileName);
// Construct the full URL for the 400px JPEG in the "jpg" folder
string jpgUrl = $"images/jpg/{fileNameWithoutExtension}-400.jpg";
return jpgUrl;
}
// Helper method to get the file size in bytes
private long GetFileSizeInBytes(string imageUrl)
{
string filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", imageUrl.TrimStart('/').Replace("/", "\\"));
FileInfo fileInfo = new FileInfo(filePath);
return fileInfo.Exists ? fileInfo.Length : 0;
}
#endregion Public Methods #endregion Public Methods
#region Private Methods #region Private Methods

View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
namespace CatherineLynwood.Controllers
{
public class PublishingController : Controller
{
public IActionResult Index()
{
return View();
}
}
}

View File

@ -40,6 +40,7 @@ namespace CatherineLynwood.Controllers
new SitemapEntry { Url = Url.Action("Index", "TheAlphaFlame", null, Request.Scheme).TrimEnd('/'), LastModified = DateTime.UtcNow }, new SitemapEntry { Url = Url.Action("Index", "TheAlphaFlame", null, Request.Scheme).TrimEnd('/'), LastModified = DateTime.UtcNow },
new SitemapEntry { Url = Url.Action("Blog", "TheAlphaFlame", null, Request.Scheme).TrimEnd('/'), LastModified = DateTime.UtcNow }, new SitemapEntry { Url = Url.Action("Blog", "TheAlphaFlame", null, Request.Scheme).TrimEnd('/'), LastModified = DateTime.UtcNow },
new SitemapEntry { Url = Url.Action("Characters", "TheAlphaFlame", null, Request.Scheme).TrimEnd('/'), LastModified = DateTime.UtcNow }, new SitemapEntry { Url = Url.Action("Characters", "TheAlphaFlame", null, Request.Scheme).TrimEnd('/'), LastModified = DateTime.UtcNow },
new SitemapEntry { Url = Url.Action("Discovery", "TheAlphaFlame", null, Request.Scheme).TrimEnd('/'), LastModified = DateTime.UtcNow },
// Additional static pages // Additional static pages
}; };

View File

@ -11,7 +11,7 @@ using SendGrid.Helpers.Mail;
namespace CatherineLynwood.Controllers namespace CatherineLynwood.Controllers
{ {
[Route("the-alpha-flame")] [Route("the-alpha-flame")]
public class TheAlphaFlame : Controller public class TheAlphaFlameController : Controller
{ {
#region Private Fields #region Private Fields
@ -21,7 +21,7 @@ namespace CatherineLynwood.Controllers
#region Public Constructors #region Public Constructors
public TheAlphaFlame(DataAccess dataAccess) public TheAlphaFlameController(DataAccess dataAccess)
{ {
_dataAccess = dataAccess; _dataAccess = dataAccess;
} }
@ -94,6 +94,18 @@ namespace CatherineLynwood.Controllers
return View("DefaultTemplate", blog); return View("DefaultTemplate", blog);
} }
[Route("chapters/chapter-1-beth")]
public IActionResult Chapter1()
{
return View();
}
[Route("chapters/chapter-2-maggie")]
public IActionResult Chapter2()
{
return View();
}
[Route("characters")] [Route("characters")]
public IActionResult Characters() public IActionResult Characters()
{ {
@ -149,6 +161,19 @@ namespace CatherineLynwood.Controllers
return RedirectToAction("BlogItem", new { slug = blogUrl, showThanks = showThanks }); return RedirectToAction("BlogItem", new { slug = blogUrl, showThanks = showThanks });
} }
[Route("discovery")]
public IActionResult Discovery()
{
return View();
}
[BookAccess(1, 1)]
[Route("extras")]
public IActionResult Extras()
{
return View();
}
public IActionResult Index() public IActionResult Index()
{ {
return View(); return View();
@ -166,6 +191,18 @@ namespace CatherineLynwood.Controllers
return View(); return View();
} }
[Route("reckoning")]
public IActionResult Reckoning()
{
return View();
}
[Route("redemption")]
public IActionResult Redemption()
{
return View();
}
[Route("characters/rick")] [Route("characters/rick")]
public IActionResult Rick() public IActionResult Rick()
{ {
@ -196,22 +233,8 @@ namespace CatherineLynwood.Controllers
return View(); return View();
} }
[Route("chapters/chapter-1-beth")]
public IActionResult Chapter1()
{
return View();
}
[Route("chapters/chapter-2-maggie")]
public IActionResult Chapter2()
{
return View();
}
[Route("front-cover")]
public IActionResult FrontCover()
{
return View();
}
#endregion Public Methods #endregion Public Methods

View File

@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
public class BookAccessAttribute : Attribute, IAsyncAuthorizationFilter
{
private readonly int _requiredLevel;
private readonly int _requiredBook;
public BookAccessAttribute(int requiredLevel, int requiredBook)
{
_requiredLevel = requiredLevel;
_requiredBook = requiredBook;
}
public Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var session = context.HttpContext.Session;
var level = session.GetInt32("BookAccessLevel");
var book = session.GetInt32("BookAccessMax");
if (level == null || book == null || level < _requiredLevel || book < _requiredBook)
{
var currentUrl = context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;
context.HttpContext.Items["RequestedUrl"] = currentUrl; // store temporarily
context.Result = new RedirectToActionResult("Prompt", "Access", new { returnUrl = currentUrl });
}
return Task.CompletedTask;
}
}

View File

@ -0,0 +1,11 @@
namespace CatherineLynwood.Models
{
public class AccessCode
{
public int PageNumber { get; set; }
public int WordIndex { get; set; }
public string ExpectedWord { get; set; }
public int AccessLevel { get; set; } // 1 = basic, 2 = retail, 3 = deluxe
public int BookNumber { get; set; } // 1, 2, or 3
}
}

View File

@ -4,10 +4,9 @@ namespace CatherineLynwood.Models
{ {
public class BlogComment public class BlogComment
{ {
[Required(ErrorMessage = "Please enter your age.")] [Required(ErrorMessage = "Please select your age group.")]
[Range(18, 120, ErrorMessage = "You must be at least 18 years old.")]
[Display(Name = "Your Age", Prompt = "Your age")] [Display(Name = "Your Age", Prompt = "Your age")]
public int Age { get; set; } public string Age { get; set; }
public int BlogID { get; set; } public int BlogID { get; set; }

View File

@ -0,0 +1,34 @@
using System.ComponentModel.DataAnnotations;
namespace CatherineLynwood.Models
{
public class Marketing
{
#region Public Properties
[Required(ErrorMessage = "Please select your age group.")]
[Display(Name = "Your Age", Prompt = "Your age")]
public string Age { get; set; }
[Required(ErrorMessage = "Please enter your email address.")]
[EmailAddress(ErrorMessage = "Please enter a valid email address.")]
[Display(Name = "Your Email Address", Prompt = "Your email address")]
public string Email { get; set; } = string.Empty;
[Required(ErrorMessage = "Please enter your name.")]
[Display(Name = "Your Name", Prompt = "Your name")]
public string Name { get; set; } = string.Empty;
public bool optExtras { get; set; }
public bool optFutureBooks { get; set; }
public bool optNews { get; set; }
[Required(ErrorMessage = "Please select your sex, or prefer not to say option.")]
[Display(Name = "Your Sex", Prompt = "Your sex")]
public string Sex { get; set; } = string.Empty;
#endregion Public Properties
}
}

View File

@ -6,7 +6,7 @@ namespace CatherineLynwood.Models
{ {
#region Public Properties #region Public Properties
public int Age { get; set; } public string Age { get; set; } = string.Empty;
public string EmailAddress { get; set; } = string.Empty; public string EmailAddress { get; set; } = string.Empty;

View File

@ -4,10 +4,9 @@ namespace CatherineLynwood.Models
{ {
public class Question public class Question
{ {
[Required(ErrorMessage = "Please enter your age.")] [Required(ErrorMessage = "Please select your age group.")]
[Range(18, 120, ErrorMessage = "You must be at least 18 years old.")]
[Display(Name = "Your Age", Prompt = "Your age")] [Display(Name = "Your Age", Prompt = "Your age")]
public int Age { get; set; } public string Age { get; set; }
[Required(ErrorMessage = "Please enter your question.")] [Required(ErrorMessage = "Please enter your question.")]
[Display(Name = "Your Question", Prompt = "Your question")] [Display(Name = "Your Question", Prompt = "Your question")]

View File

@ -1,7 +1,8 @@
using System.IO.Compression; using System.IO.Compression;
using CatherineLynwood.Middleware; using CatherineLynwood.Middleware;
using CatherineLynwood.Services; using CatherineLynwood.Services;
using Microsoft.AspNetCore.ResponseCompression; using Microsoft.AspNetCore.ResponseCompression;
using WebMarkupMin.AspNetCoreLatest; using WebMarkupMin.AspNetCoreLatest;
@ -24,6 +25,17 @@ namespace CatherineLynwood
// Add IHttpContextAccessor for accessing HTTP context in tag helpers // Add IHttpContextAccessor for accessing HTTP context in tag helpers
builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpContextAccessor();
// ✅ Add session services (in-memory only)
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
// ✅ Register the book access code service
builder.Services.AddScoped<IAccessCodeService, AccessCodeService>();
// Add response compression services // Add response compression services
builder.Services.AddResponseCompression(options => builder.Services.AddResponseCompression(options =>
{ {
@ -49,7 +61,6 @@ namespace CatherineLynwood
}) })
.AddHtmlMinification(); .AddHtmlMinification();
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@ -69,6 +80,9 @@ namespace CatherineLynwood
app.UseWebMarkupMin(); app.UseWebMarkupMin();
// ✅ Enable session BEFORE authorization
app.UseSession();
app.UseAuthorization(); app.UseAuthorization();
app.MapControllerRoute( app.MapControllerRoute(

View File

@ -0,0 +1,53 @@
using CatherineLynwood.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CatherineLynwood.Services
{
public interface IAccessCodeService
{
Task<(int pageNumber, int wordIndex)> GetCurrentChallengeAsync();
Task<(int accessLevel, int highestBook)> ValidateWordAsync(string userWord);
}
public class AccessCodeService : IAccessCodeService
{
private readonly List<AccessCode> _accessCodes;
public AccessCodeService()
{
_accessCodes = new List<AccessCode>
{
// Book 1 codes
new AccessCode { PageNumber = 168, WordIndex = 3, ExpectedWord = "apple", AccessLevel = 1, BookNumber = 1 },
new AccessCode { PageNumber = 168, WordIndex = 3, ExpectedWord = "forest", AccessLevel = 2, BookNumber = 1 },
new AccessCode { PageNumber = 168, WordIndex = 3, ExpectedWord = "phoenix", AccessLevel = 3, BookNumber = 1 },
// Future: Book 2 codes (example)
new AccessCode { PageNumber = 304, WordIndex = 6, ExpectedWord = "ember", AccessLevel = 2, BookNumber = 2 },
new AccessCode { PageNumber = 304, WordIndex = 6, ExpectedWord = "ashes", AccessLevel = 3, BookNumber = 2 }
};
}
public Task<(int pageNumber, int wordIndex)> GetCurrentChallengeAsync()
{
var challenge = _accessCodes.First(); // current prompt
return Task.FromResult((challenge.PageNumber, challenge.WordIndex));
}
public Task<(int accessLevel, int highestBook)> ValidateWordAsync(string userWord)
{
var match = _accessCodes.FirstOrDefault(c =>
c.ExpectedWord.Equals(userWord, StringComparison.OrdinalIgnoreCase));
if (match != null)
return Task.FromResult((match.AccessLevel, match.BookNumber));
return Task.FromResult((0, 0)); // invalid
}
}
}

View File

@ -42,7 +42,7 @@ namespace CatherineLynwood.Services
{ {
questions.AskedQuestions.Add(new Question questions.AskedQuestions.Add(new Question
{ {
Age = GetDataInt(rdr, "Age"), Age = GetDataString(rdr, "Age"),
EmailAddress = GetDataString(rdr, "EmailAddress"), EmailAddress = GetDataString(rdr, "EmailAddress"),
Name = GetDataString(rdr, "Name"), Name = GetDataString(rdr, "Name"),
Text = GetDataString(rdr, "Question"), Text = GetDataString(rdr, "Question"),
@ -275,6 +275,40 @@ namespace CatherineLynwood.Services
return visible; return visible;
} }
public async Task<bool> AddMarketingAsync(Marketing marketing)
{
bool success = true;
using (SqlConnection conn = new SqlConnection(_connectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
try
{
await conn.OpenAsync();
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "SaveMarketingOptions";
cmd.Parameters.AddWithValue("@Name", marketing.Name);
cmd.Parameters.AddWithValue("@Email", marketing.Email);
cmd.Parameters.AddWithValue("@OptExtras", marketing.optExtras);
cmd.Parameters.AddWithValue("@OptFutureBooks", marketing.optFutureBooks);
cmd.Parameters.AddWithValue("@OptNews", marketing.optNews);
cmd.Parameters.AddWithValue("@Age", marketing.Age);
cmd.Parameters.AddWithValue("@Sex", marketing.Sex);
await cmd.ExecuteNonQueryAsync();
}
catch (Exception ex)
{
success = false;
}
}
}
return success;
}
public async Task<bool> AddQuestionAsync(Question question) public async Task<bool> AddQuestionAsync(Question question)
{ {
bool visible = false; bool visible = false;

View File

@ -46,10 +46,11 @@ namespace CatherineLynwood.TagHelpers
string fileName = Path.GetFileNameWithoutExtension(rootPath); string fileName = Path.GetFileNameWithoutExtension(rootPath);
string extension = Path.GetExtension(rootPath); string extension = Path.GetExtension(rootPath);
string year = DateTime.Now.Year.ToString();
// Define paths for "webp" and "jpg" subfolders // Define paths for "webp" and "jpg" subfolders
string webpDirectory = Path.Combine(directory, "webp"); string webpDirectory = Path.Combine(directory, "webp");
string jpgDirectory = Path.Combine(directory, "jpg"); string jpgDirectory = Path.Combine(directory, "jpg");
string watermarkText = "© Catherine Lynwood 2024"; string watermarkText = $"© Catherine Lynwood {year}";
// Ensure the subdirectories exist // Ensure the subdirectories exist
Directory.CreateDirectory(webpDirectory); Directory.CreateDirectory(webpDirectory);

View File

@ -5,45 +5,44 @@ namespace CatherineLynwood.TagHelpers
[HtmlTargetElement("social-media-share")] [HtmlTargetElement("social-media-share")]
public class SocialMediaShareTagHelper : TagHelper public class SocialMediaShareTagHelper : TagHelper
{ {
// The URL of the page to share
public string Url { get; set; } public string Url { get; set; }
// Optional title for the shared content
public string Title { get; set; } public string Title { get; set; }
// Additional CSS classes for the div
public string Class { get; set; } public string Class { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
// Ensure Url is encoded var encodedUrl = $"https://www.catherinelynwood.com{Url}";
var encodedUrl = $"https://www.catherinelynwood.com{Url}"; // Replace with a default if URL is not provided
var encodedTitle = Title ?? "Check this out!"; var encodedTitle = Title ?? "Check this out!";
// Define the social media sharing URLs
var facebookUrl = $"https://www.facebook.com/sharer/sharer.php?u={encodedUrl}"; var facebookUrl = $"https://www.facebook.com/sharer/sharer.php?u={encodedUrl}";
var twitterUrl = $"https://twitter.com/intent/tweet?url={encodedUrl}&text={encodedTitle}"; var twitterUrl = $"https://twitter.com/intent/tweet?url={encodedUrl}&text={encodedTitle}";
var linkedinUrl = $"https://www.linkedin.com/sharing/share-offsite/?url={encodedUrl}"; var linkedinUrl = $"https://www.linkedin.com/sharing/share-offsite/?url={encodedUrl}";
var pinterestUrl = $"https://pinterest.com/pin/create/button/?url={encodedUrl}&description={encodedTitle}"; var pinterestUrl = $"https://pinterest.com/pin/create/button/?url={encodedUrl}&description={encodedTitle}";
// Set the tag output var shareHtml = $@"
output.TagName = "p"; // container for the social media buttons <div class='share-section'>
<p>Enjoyed this page? Share it:</p>
<a href='{facebookUrl}' target='_blank' rel='noopener' class='share-button facebook'><i class='fab fa-facebook-square'></i></a>
<a href='{twitterUrl}' target='_blank' rel='noopener' class='share-button twitter'><i class='fab fa-twitter'></i></a>
<a href='{linkedinUrl}' target='_blank' rel='noopener' class='share-button linkedin'><i class='fab fa-linkedin'></i></a>
<a href='{pinterestUrl}' target='_blank' rel='noopener' class='share-button pinterest'><i class='fab fa-pinterest-square'></i></a>
</div>";
var followHtml = @"
<div class='follow-section mt-3'>
<small>Want to follow Catherine Lynwood?</small><br/>
<a href='https://twitter.com/@cathlynwood' target='_blank' rel='noopener' class='follow-icon'><i class='fab fa-twitter'></i></a>
<a href='https://www.linkedin.com/in/catherine-lynwood-73978433a' target='_blank' rel='noopener' class='follow-icon'><i class='fab fa-linkedin'></i></a>
<a href='https://www.tiktok.com/@catherinelynwood' target='_blank' rel='noopener' class='follow-icon'><i class='fab fa-tiktok'></i></a>
</div>";
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag; output.TagMode = TagMode.StartTagAndEndTag;
// Apply the passed CSS classes along with "social-media-share" default class
var cssClass = string.IsNullOrEmpty(Class) ? "social-media-share" : $"social-media-share {Class}"; var cssClass = string.IsNullOrEmpty(Class) ? "social-media-share" : $"social-media-share {Class}";
output.Attributes.SetAttribute("class", cssClass); output.Attributes.SetAttribute("class", cssClass);
// Construct HTML for each button output.Content.SetHtmlContent(shareHtml + followHtml);
var content = $@"
<a href='{facebookUrl}' target='_blank' class='share-button facebook'><i class='fab fa-facebook-square'></i></a>
<a href='{twitterUrl}' target='_blank' class='share-button twitter'><i class='fab fa-twitter-square'></i></a>
<a href='{linkedinUrl}' target='_blank' class='share-button linkedin'><i class='fab fa-linkedin'></i></a>
<a href='{pinterestUrl}' target='_blank' class='share-button pinterest'><i class='fab fa-pinterest-square'></i></a>
";
// Set the inner HTML for the output
output.Content.SetHtmlContent(content);
} }
} }
} }

View File

@ -0,0 +1,112 @@
@model CatherineLynwood.Models.Marketing
@{
ViewData["Title"] = "Join the Mailing List";
}
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 class="mb-4">Would you like to stay in touch?</h2>
<p>Wed love to keep you updated, but only if you want to be.</p>
<p>As a thank you, you will be granted access to even more great exclusive content. Don't miss out!</p>
<form asp-action="MailingList" id="signUpForm" class="row">
<div class="col-12 text-dark">
<div class="form-floating mb-3">
<input asp-for="Name" name="Name" class="form-control">
<label asp-for="Name"></label>
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="col-12 text-dark">
<div class="form-floating mb-3">
<input asp-for="Email" name="Email" type="email" class="form-control">
<label asp-for="Email"></label>
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
<div class="col-12">
<p>You don't have to tell me your age or sex, but it would really help me understand my readers if you do.</p>
</div>
<div class="col-6 text-dark">
<div class="form-floating mb-3">
<select asp-for="Age" name="Age" class="form-select" aria-label="Select your age">
<option value="" selected>Select your age</option>
<option value="18-24">1824</option>
<option value="25-34">2534</option>
<option value="35-44">3544</option>
<option value="45-54">4554</option>
<option value="55-64">5564</option>
<option value="65+">65+</option>
<option value="0">Prefer not to say</option>
</select>
<label asp-for="Age"></label>
<span asp-validation-for="Age" class="text-danger"></span>
</div>
</div>
<div class="col-6 text-dark">
<div class="form-floating mb-3">
<select asp-for="Sex" name="Sex" class="form-select" aria-label="Select your sex">
<option value="" selected>Select Sex</option>
<option value="female">Female</option>
<option value="male">Male</option>
<option value="other">Other</option>
<option value="prefer-not-to-say">Prefer not to say</option>
</select>
<label asp-for="Sex"></label>
<span asp-validation-for="Sex" class="text-danger"></span>
</div>
</div>
<div class="col-12">
<div class="form-check mb-2">
<input asp-for="optNews" class="form-check-input" type="checkbox" />
<label asp-for="optNews" class="form-check-label">
Yes, Id like news about the Alpha Flame trilogy and future books
</label>
</div>
<div class="form-check mb-2">
<input asp-for="optExtras" class="form-check-input" type="checkbox" name="optExtras" />
<label asp-for="optExtras" class="form-check-label">
Yes, send me links to bonus content and special extras
</label>
</div>
<div class="form-check mb-3">
<input asp-for="optFutureBooks" class="form-check-input" type="checkbox" />
<label asp-for="optFutureBooks" class="form-check-label">
Let me know when Catherine Lynwood publishes something new
</label>
</div>
<p class="small">
We respect your privacy. You can unsubscribe at any time. View our <a href="/Privacy">privacy policy</a>.
</p>
</div>
</form>
<form asp-action="Decline" id="declineForm" class="row">
</form>
<div class="row">
<div class="col-6 d-grid">
<button type="submit" form="signUpForm" class="btn btn-primary">Continue</button>
</div>
<div class="col-6 text-end">
<button type="submit" form="declineForm" class="btn btn-primary">No Thanks</button>
</div>
</div>
</div>
</div>
</div>
@section Meta{
<meta name="robots" content="noindex, nofollow">
}

View File

@ -0,0 +1,56 @@
@{
ViewData["Title"] = "Verify Book Access";
int pageNumber = ViewBag.PageNumber;
int wordIndex = ViewBag.WordIndex;
string error = ViewBag.Error as string;
}
<div class="container mt-5">
<div class="row justify-content-center align-items-center">
<div class="col-md-2 mb-4 mb-md-0 d-none d-md-block">
<responsive-image src="unlock-extras.png" alt="Unlock Alpha Flame Extras" class="img-fluid rounded-circle border border-3 border-dark shadow-lg" display-width-percentage="50"></responsive-image>
</div>
<div class="col-md-10">
<h2 class="mb-4">Unlock Your Bonus Content</h2>
<p>
Thank you for purchasing <em>The Alpha Flame: Discovery</em>.
To access the exclusive extras section, including behind-the-scenes notes, artwork, and more, please verify that you own a physical copy of the book.
</p>
<div class="alert alert-info small">
This check only works with paperback and hardback editions. Unfortunately, Kindle editions may not show consistent page numbers or word positions, so access is limited to physical copies for now.
</div>
<form method="post" asp-controller="Access" asp-action="Prompt">
<input type="hidden" name="returnUrl" value="@ViewBag.ReturnUrl" />
<p>
Please enter the word found on <strong>page @pageNumber</strong>, word <strong>@wordIndex</strong> in your copy.
</p>
<div class="mb-3">
<input type="text" name="userWord" class="form-control" required autofocus placeholder="Enter the word here..." />
</div>
@if (!string.IsNullOrEmpty(error))
{
<div class="alert alert-danger">@error</div>
}
<button type="submit" class="btn btn-dark">Unlock Extras</button>
</form>
<p class="text-muted mt-4 small">
Your privacy is important. This verification is a one-time check and no personal data is stored.
</p>
</div>
</div>
</div>
@section Meta {
<meta name="robots" content="noindex, nofollow">
}

View File

@ -95,10 +95,13 @@
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<select asp-for="Age" name="Age" class="form-select" aria-label="Select your age"> <select asp-for="Age" name="Age" class="form-select" aria-label="Select your age">
<option value="" selected>Select your age</option> <option value="" selected>Select your age</option>
@for (var age = 18; age <= 120; age++) <option value="18-24">1824</option>
{ <option value="25-34">2534</option>
<option value="@age">@age</option> <option value="35-44">3544</option>
}) <option value="45-54">4554</option>
<option value="55-64">5564</option>
<option value="65+">65+</option>
<option value="0">Prefer not to say</option>
</select> </select>
<label asp-for="Age"></label> <label asp-for="Age"></label>
<span asp-validation-for="Age" class="text-danger"></span> <span asp-validation-for="Age" class="text-danger"></span>

View File

@ -0,0 +1,160 @@
@{
ViewData["Title"] = "The Alpha Flame | Chapter 1 Excerpt";
}
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Extras">Extras</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Extras">Discovery</a></li>
<li class="breadcrumb-item active" aria-current="page">Epilogue</li>
</ol>
</nav>
</div>
</div>
<!-- Header -->
<div class="text-center mb-5">
<h1 class="fw-bold">The Alpha Flame: Discovery</h1>
</div>
<!-- Excerpt Content -->
<div class="row gx-5">
<!-- Audio and Text -->
<div class="col-12">
<div class="bg-white rounded-5 border border-3 border-dark shadow-lg p-3">
<responsive-image src="discovery-epilogue.png" class="card-img-top" alt="The Gang Having a Drink at The Barnt Green Inn" display-width-percentage="100"></responsive-image>
<!-- Audio Player -->
<div class="audio-player text-center">
<audio controls>
<source src="/audio/discovery-epilogue.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
</div>
<div class="text-black text-center">
<h2>Epilogue</h2>
<h3>Narrated by Maggie Late May 1983</h3>
</div>
<!-- Text Content -->
<div class="chapter-text pt-3">
<p><em>Beth and I pulled into the car park of the Barnt Green Inn with the roof down, the late afternoon sun warming our faces. Everything looked more vivid lately, the colours brighter, the air lighter. It was like the whole world had released a breath.</em></p>
<p><em>I locked the car, and we wandered round to the beer garden. Rob and Zoe were already there, sat close, chatting like old friends. Even now, after everything, it still surprised me to see them so relaxed together.</em></p>
<p>Rob spotted us and raised a hand. “Hey!”</p>
<p>I leaned down and kissed him on the cheek. “Hiya. Can you get us a drink?”</p>
<p>“Of course. What do you fancy?”</p>
<p>“Coke for me. Beth?”</p>
<p>She gave a small smile. “Cider, please.”</p>
<p><em>Rob nodded and headed for the bar.</em></p>
<p><em>Beth and I took the seats opposite Zoe.</em></p>
<p>“Howve you both been?” Zoe asked, giving us a once-over.</p>
<p>I glanced at Beth. “Good… I think. Still getting used to it all.”</p>
<p>Beth nodded. “Yeah. Im alright. Put some weight on. Im nearly as fat as Maggie now,” she grinned.</p>
<p>I laughed, nudging her. “Nearly? That ship has sailed, love.”</p>
<p>“Mums fault. Too many sausage sandwiches.”</p>
<p>“You both look good,” Zoe said, eyes lingering just a little longer on Beth. “Bruises gone?”</p>
<p><em>We nodded.</em></p>
<p>“So, what have you two been doing with yourselves?”</p>
<p>Beth perked up. “Helping Maggie with her designs. Turns out Im not bad with a needle.”</p>
<p>“And shes not a bad model either,” I added. “Definitely helps having someone try things on.”</p>
<p>Zoe smirked. “Do you make her twirl like they do on those fashion shows?”</p>
<p>Beth put on a mock pout. “She makes me pose like Im in Vogue. Arms here, head there.”</p>
<p>“Only when youre being annoying,” I said, laughing. “Besides, you love it.”</p>
<p>“True,” Beth admitted. “Its actually fun. I never thought Id enjoy something like that.”</p>
<p><em>Laughter echoed behind us as Rosie and Rebecca came round the corner.</em></p>
<p>“Shes deadly,” Rebecca giggled. “I had my eyes closed the whole way here.”</p>
<p>“It wasnt that bad!” Rosie huffed, trying to look offended. “Not my fault people kept jumping out in front of me.”</p>
<p>“You might try braking instead of shouting. Its far more effective,” Rebecca teased.</p>
<p>“Wheres Rob?” Rosie asked.</p>
<p>“Hes at the bar. If youre quick, you might get a free drink,” I said.</p>
<p><em>Right on cue, Rob returned with a tray.</em></p>
<p>He clocked the new arrivals and sighed. “Im going back to the bar, arent I?”</p>
<p>He placed the drinks down, then turned with theatrical weariness. “The usual, girls?”</p>
<p>“Yes please,” said Rebecca sweetly.</p>
<p><em>Once he was back and settled, we all relaxed into the rhythm of easy chatter.</em></p>
<p>“So, whos got summer plans then?” Rosie asked. “Please tell me someones going somewhere glamorous.”</p>
<p>“Barnt Green counts as glamorous, right?” I said.</p>
<p>“Only if you squint,” said Zoe. “And ignore the smell of wet dog that always seems to hang around the canal.”</p>
<p>“I might take Beth to London,” I said. “Show her the big city.”</p>
<p>Beth raised an eyebrow. “What for?”</p>
<p>“So, you can be horrified at the price of everything and then come home saying how much nicer Birmingham is.”</p>
<p>“Sold,” she laughed.</p>
<p>Zoe leaned forward, lowering her voice slightly. “I heard from Graham. The case against Ricks progressing.”</p>
<p><em>Beth stiffened slightly but nodded.</em></p>
<p>“Are you two going to be alright when it comes to court?”</p>
<p><em>Beth and I exchanged a look. Wed talked about it endlessly in private.</em></p>
<p>“We think so,” Beth said. “Its black and white for us. We just have to tell the truth.”</p>
<p><em>Rob had gone quiet, his brow furrowed.</em></p>
<p>“You alright?” I asked.</p>
<p>He hesitated, then said, “Its just… I dont believe in coincidences. Not ones like that.”</p>
<p>Rebecca cocked her head. “Is he always this cryptic?”</p>
<p>“Most of the time,” I said. “This ones new, though. Go on, Rob. Spit it out.”</p>
<p>“Rick,” he said. “The night Beth ended up under the flyover. Him just being there… it never sat right with me.”</p>
<p>Beths face fell still. “You think he was following me?”</p>
<p>Rob gave a half-shrug. “Feels too neat to be chance.”</p>
<p>Beth looked down. “He did have the flat, though. Cindy lived there too, remember. Maybe he was nearby anyway.”</p>
<p>“Maybe,” Rob said, but not like he believed it.</p>
<p>Rosie clapped her hands lightly. “Well, on a brighter note, Gregs birthday is next week. Hes throwing a party. Youre all invited.”</p>
<p>Beths eyes lit up. “Ive never been to a grown-up party. Not really. Im in.”</p>
<p>“Youll need something to wear,” I said. “And no, youre not stealing that red skirt again.”</p>
<p>“I only borrowed it.”</p>
<p>“For three weeks.”</p>
<p>Rosie smirked. “Are you two dressing the same again?”</p>
<p>“Obviously,” we said in unison.</p>
<p>Zoe groaned. “Have you noticed they do that constantly now?” She turned to Rob. “Seriously, get out while you still can.”</p>
<p><em>Beth and I grinned at each other.</em></p>
<p>“I really dont know what theyre…”</p>
<p>“…on about. Do you?” we said, still in sync.</p>
<p>Rebecca had been quiet, but now her voice was cautious. “Are you going to look for your dad?”</p>
<p><em>We both paused.</em></p>
<p>“We would like to,” I replied. “We havent really got too much to go on. There are a few things weve got to follow up in Beths memory tin. Theres a bank book for one. Its only got one pound seventy-nine in it, but it might give us a clue.”</p>
<p>Beth added. “Weve also got the wedding photos… and a date. Oh, and even the name of the church. So, we might be able to find something there, if we can find the right church.”</p>
<p><em>The table fell quiet for a moment.</em></p>
<p>“Did your mum ever talk about him?” Rebecca asked.</p>
<p>“Not really,” Beth said. “She used to say Hes nobody worth knowing. But Im not sure she meant it.”</p>
<p>Rosie glanced up. “Its such a lovely day. We should go to the beach one weekend.”</p>
<p>Beths eyes went wide. “Yes! All of us. Itd be amazing.”</p>
<p>“Ill bring sandwiches,” said Rob. “Beth, youre banned from cooking anything though.”</p>
<p>“Hey! That cheese toastie was only slightly burnt.”</p>
<p>“It was charcoal.”</p>
<p>“I quite liked it,” I added. “Adds crunch.”</p>
<p><em>General agreement followed.</em></p>
<p>“I need the loo,” said Rebecca.</p>
<p>“Me too. Ill grab drinks on the way back. Same again?”</p>
<p>“Perfect,” said Zoe.</p>
<p>Once they were out of earshot, Zoe leaned in. “She really doesnt know, does she? About Sophie.”</p>
<p><em>We shook our heads.</em></p>
<p>“Theyre nothing alike,” I said. “Different planets.”</p>
<p>“Sophie still avoiding you?” Zoe asked.</p>
<p>I nodded. “Mostly. I saw her once. She didnt stop.”</p>
<p>Beths face darkened. “I can still see her face. That night. Just after she gave the order.”</p>
<p>Zoe blinked. “You think she did?”</p>
<p>Beth didnt hesitate. “She knew what Rick was going to do. That club… theres more to it. You think that, dont you?”</p>
<p>Zoe nodded slowly. “Graham thinks so too. Says something stinks, but he hasnt nailed it yet.”</p>
<p>Beths voice dropped to a whisper. “Mum wasnt killed for nothing. Adam either. Rick even said so.”</p>
<p>“Has Graham got anything else out of Rick?” I asked.</p>
<p>“Nothing solid,” Zoe replied. “Hes clammed up. Hes gone No comment on everything.”</p>
<p>“And our aunt? Still scared?” Beth asked.</p>
<p>“Hes working on her. Shes terrified. Hes got to go gently.”</p>
<p>Beths voice hardened. “What about Baker?”</p>
<p>Zoes face tightened. “Hes not in the frame. Yet. Grahams gathering evidence, but if he pushes too soon, Baker will cover his tracks.”</p>
<p><em>Rebecca and Rosie returned, laughing.</em></p>
<p>“What have you two done now?” I asked.</p>
<p>“She dropped a tray of drinks on some poor guy,” Rosie grinned. “Shes worse than Rob.”</p>
<p>“Oi!” Rob protested. “That was once.”</p>
<p>“Twice,” I said, grinning, and leaned in to kiss him.</p>
<p>Beth rolled her eyes. “Theyre going to be unbearable if they stay this happy.”</p>
<p>“Jealous?” I teased.</p>
<p>“A bit,” she admitted, then smiled. “But in the good way.”</p>
<p><em>The sun dipped lower, the sky glowing amber. For now, we had peace. But we hadnt finished. Not yet. The flame had only just started to burn.</em></p>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,373 @@

<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Extras">Extras</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Extras">Discovery</a></li>
<li class="breadcrumb-item active" aria-current="page">Maggie's Designs</li>
</ol>
</nav>
</div>
</div>
<div class="container">
<h1 class="mb-5 text-center">Maggie's Designs</h1>
<p>
I love fashion and I trued to weave that into Maggie's charactger. Helped by AI I really enjoyed coming up with outfits
for Maggie to wear in the various scenes of the book. Lots were so far out there that they didn't make it to the final edit,
or the descriptions were so detailed that you've had nodded off.
</p>
<p>
That said, no matter what the outfit was I found working from a visual prompt enable me to write more vividly about it.
</p>
<!-- Section 1 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-1">
<responsive-image src="maggie-fashion-6.png" class="img-fluid" alt="The Elle Dress" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“She didnt dress to impress. She dressed to become, a force wrapped in colour, stitched in self-belief.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“The Elle Dress” Fully Formed</h5>
<p>This is it, the dress that stopped hearts and turned pages. The one Maggie wore for *Elle*, unapologetic and unforgettable. Theres nothing shy about this piece. Its all precision and provocation; a sculpted plunge, a defiant cut-out, a hemline that dances between lingerie and high fashion. Every detail speaks Maggies language, fire without fuss, beauty without permission. She didnt just wear this dress… she claimed it. And in doing so, she claimed herself.</p>
<p>The deep teal shimmered like danger in low light, somewhere between mermaid and menace. I remember writing the scene and thinking, *this isnt about being sexy, its about being seen*. This dress is armour. Soft in texture, sharp in purpose. The fishnet tights? That was Maggies touch. A reminder that no matter how glossy the set, she brought her own edge with her. Always.</p>
<p>There may be another version of this dress later, refined, reimagined. But this one? This is the original. The raw truth. The moment the world turned to look… and Maggie didnt flinch.</p>
</div>
</div>
<!-- Section 2 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-2">
<responsive-image src="maggie-fashion-12.png" class="img-fluid" alt="Forest Siren" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“She didnt rise from ashes. She bloomed from the soil, raw, rooted, and wild beyond taming.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Forest Siren” The Evolution of Elle</h5>
<p>This is what happens when a woman finds her voice, when the flame that once flickered is now fully ablaze, controlled, focused, and utterly arresting. This dress is the next chapter after the *Elle* shoot, not just an outfit, but a statement. A transformation. A whispered prophecy realised. The original was power through seduction… but this? This is power through presence.</p>
<p>I imagined Maggie walking barefoot across stone in this. Not for a crowd. Not even for the camera. Just for herself. The soft, trailing green, almost moss-like in motion, conjures wild things and whispered rebellions. The floral lace still clings, but it no longer begs to be noticed. It simply exists, unafraid, untamed. The high slit and fishnets remain, a signature. A nod to the girl who fought to survive. But the gown? That belongs to the woman shes become.</p>
<p>Theres a reason this version was never photographed for the magazine. It wasnt fashion anymore. It was folklore. A garment you glimpse once and never forget. And like Maggie, it doesnt ask you to understand it. It only asks that you remember.</p>
</div>
</div>
<!-- Section 3 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-3">
<responsive-image src="maggie-fashion-3.png" class="img-fluid" alt="Ivory Fire" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“She didnt wear it to be wanted. She wore it to be undeniable.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Ivory Fire” The One That Smouldered Off-Page</h5>
<p>This dress never appeared in the book, but it haunted the edges of it. I imagined Maggie in it once, just once, and the image never left. It was lace, yes, but not gentle. The kind of lace that clung like memory and cut like truth. It wasnt designed to cover; it was designed to challenge. Petals traced over her chest like secrets too dangerous to speak aloud, their edges dipping into skin with a kind of deliberate precision that made it impossible to ignore her.</p>
<p>She didnt wear this to seduce. She wore it to reclaim. I pictured her standing still in it while the world moved around her, daring it to catch up. The neckline plunged, but it was her gaze that undressed the room. In the end, it was too much for the scene I was writing, too sharp, too strong, too unforgettable. So I left it behind. But like so much of Maggie, it lived on in the shadows between pages. Not forgotten. Just waiting.</p>
</div>
</div>
<!-- Section 4 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-4">
<responsive-image src="maggie-fashion-4.png" class="img-fluid" alt="Ember Veins" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“It burned beneath the fabric, not just colour, but something molten and unspoken. She was the match and the flame.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Ember Veins” The Prototype</h5>
<p>This was the dress that nearly made it, an early vision of what would eventually evolve into Maggies infamous jumpsuit in Chapter 7. I called it *Ember Veins* because the pattern reminded me of fire trapped under silk, alive just beneath the surface. The fabric moves like its breathing. Every flick of orange, red, and teal threads through the design like molten emotion stitched into form. Its bold, unapologetic… and yet, it never quite felt like the right fit for the scene. Too regal. Too statuesque. Not enough of Maggies street-born swagger.</p>
<p>But the essence is here. The deep plunge that dares the room to judge her. The sculpted waist that declares power, not permission. And the colours, oh, the colours. They felt like Maggies moods during that chapter: blazing, unpredictable, and impossible to ignore. This wasnt something she would wear to blend in; it was what shed wear to set a room on fire.</p>
<p>Ultimately, the jumpsuit won, it had grit, mobility, and a whisper of rebellion. But *Ember Veins* still has a place in Maggies story. Not on the page, perhaps… but in the margins, smouldering quietly, waiting to be remembered.</p>
</div>
</div>
<!-- Section 5 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-1">
<responsive-image src="maggie-fashion-5.png" class="img-fluid" alt="Midnight Teal" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“It wasnt about seduction. It was about control, about saying, You can look… but you dont get to touch.’”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Midnight Teal” The Dress Before Elle</h5>
<p>Before Maggie stunned the world in the pages of *Elle*, there was this. A raw, electric concept that pulsed with possibility. I called it *Midnight Teal*, a piece that sat somewhere between lingerie and defiance, stitched not for comfort but for confrontation. This was Maggie untamed, unfiltered, unapologetically herself. It wasnt designed for the high street or a Paris runway… it was born for shadows and stares, for flickering candlelight and whispered thoughts.</p>
<p>The lace, tangled like secrets, reveals more than it hides. The fishnets ground her in the kind of grit only Maggie could carry. And that choker? A black ribbon that says “you can look, but you dont get to own.” I always imagined her wearing this not to seduce, but to reclaim. Not to tease, but to dare. This wasnt about being pretty. It was about being powerful.</p>
<p>Ultimately, it was too much for the magazine shoot. Elle needed elegance. This was rebellion. But I keep it here, because it mattered. Because somewhere in Maggies soul, this dress still lives, wild, sensual, fearless. A dress not worn for an audience, but for herself.</p>
</div>
</div>
<!-- Section 6 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-2">
<responsive-image src="maggie-fashion-7.png" class="img-fluid" alt="Sleek Intentions" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“I can be soft. But dont mistake me for breakable.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Sleek Intentions” The Outfit That Almost Was</h5>
<p>Before the white two-piece took its place in Chapter 15, this was the look. A vision in midnight black, bold, sculpted, unforgiving. I imagined Maggie in this as a weapon disguised as elegance. The high neck and sheer sleeves gave it structure, control… but the body-hugging lines spoke of something else entirely. Power. Restraint. And maybe a little hunger too. She wasnt dressing for flirtation; she was dressing for impact.</p>
<p>This was meant to be her first appearance at Ricardos, a table full of family, wine, and a quiet undercurrent of testing the waters. But the outfit changed because the tone did. White softened the edges. A two-piece gave her room to move, to breathe, to step into that moment with grace rather than dominance. And yet I still love this version. It shows the side of Maggie that doesnt compromise, the girl who grew up armoured in silence and attitude.</p>
<p>*Sleek Intentions* never made it to the page, but it belonged to the story all the same. The decision not to wear it says as much as if she had. Sometimes, power is in the pivot, in choosing softness when the world expects sharp.</p>
</div>
</div>
<!-- Section 1 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-1">
<responsive-image src="maggie-fashion-8.png" class="img-fluid" alt="Where the Poppies Burn" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“She didnt escape the fire. She walked through it, and the flowers grew behind her.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Where the Poppies Burn” A Dream of Freedom</h5>
<p>This one was never meant for the story itself, not directly. It was more of a whisper behind the writing. A vision I carried with me in quiet moments: Maggie, walking barefoot through a field of fire-tipped poppies, the world golden and glowing around her. Shes not looking back. She doesnt need to. Whatever held her is gone. Whatever comes next is hers to decide.</p>
<p>The dress is barely there, a gauze of lace and suggestion, soft as breath, flowing like memory. Its not about seduction, not here. Its about shedding. About choosing vulnerability in a world that demanded armour. Her hair is wild, her steps silent, and the light clings to her like it knows shes survived something most never would.</p>
<p>I once considered using this for the cover. It would have been unconventional, maybe too symbolic, but it captured a truth. Not about what Maggie wears, or where she walks, but who she is when no one is watching. This image was never part of the story on the page… but its part of the soul underneath it.</p>
</div>
</div>
<!-- Section 2 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-2">
<responsive-image src="maggie-fashion-9.png" class="img-fluid" alt="Verdant Fury" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“You dont rise from fire without learning how to burn.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Verdant Fury” The Goddess Unleashed</h5>
<p>This was never meant to be subtle. This was me asking, *what if Maggie didnt just survive… what if she ruled?* What if all the hurt, all the hunger, all the fire she'd kept bottled up was no longer something she hid, but something she wore? The result was this: *Verdant Fury*. A vision in deep emerald and gold, clinging to her like ivy laced with flame.</p>
<p>Theres a mythic quality to this look, part forest queen, part fallen angel, all defiance. The sculpted bodice doesnt just highlight her form, it *armours* it. The gloves, shredded and clinging, feel like echoes of a battle already won. She stands here not as a girl escaping the past, but as a woman whos scorched the path behind her. And those eyes, theyre not asking for permission. Theyre issuing a challenge.</p>
<p>This outfit never had a scene. It was too much to contain. Too electric, too dangerous. But it lives in the spirit of Maggie all the same. In the moments where she turns, chin lifted, and dares the world to tell her she cant. Its not fashion. Its a reckoning draped in green.</p>
</div>
</div>
<!-- Section 3 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-3">
<responsive-image src="maggie-fashion-10.png" class="img-fluid" alt="Unveiling Desires" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“She wore it like a dare, and Zoe answered with a kiss.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Unveiling Desires” The Painted Flame Jumpsuit</h5>
<p>This was never a maybe. This jumpsuit was destined to be worn. From the moment I imagined Maggie walking into that nightclub on New Years Eve, I saw her in this, a riot of colour, molten silk clinging to her with intent. Gold, vermilion, violet, turquoise… each hue brushed like fire across fabric, alive with movement, bold without apology. She didnt just wear it, she ignited it.</p>
<p>Everything about it was deliberate. The plunging neckline, the fitted waist, the shimmer that caught the light every time she turned, it was a siren song, yes, but also a declaration. She made it herself, of course. Maggies talent always came from that raw place inside her, where fire met finesse. And in this look, her artistry wasnt just visible, it was undeniable.</p>
<p>The jumpsuit became more than fashion. It was foreplay. Power. The spark that lit the fuse between her and Zoe, making their chemistry explosive and immediate. This outfit had presence. It was the flame before the kiss, the stroke before the sigh. And it belongs in this scrapbook because it didnt just make it into the book, it helped define it.</p>
</div>
</div>
<!-- Section 4 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-4">
<responsive-image src="maggie-fashion-11.png" class="img-fluid" alt="Whispers in Lace" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“She didnt wear it… but for a moment, she almost did.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Whispers in Lace” The Dress That Was Too Much</h5>
<p>This gown was a daydream. An experiment in elegance. I imagined Maggie twirling through Ricardos grand hallway, all lace and light, every step sweeping the floor like she was born to haunt ballrooms. But as soon as I saw it fully realised, I knew, this wasnt her moment for that. This dress belonged to a different story. One where Maggie danced, yes, but not in a world as grounded as hers. It was too refined, too ethereal, too… not quite right.</p>
<p>Still, theres something about it that I loved. The off-shoulder cut, the illusion of fragility, the way it billowed with every motion. It captured the romantic part of Maggie that often hides behind her fire, the dreamer, the artist, the girl who still, despite everything, believes in beauty. But I needed her to walk into Ricardos with strength, not softness. Confidence, not fantasy. This was grace when what I needed was poise with a bit of punch.</p>
<p>So the dress stayed in the wings. It never made it onto the page. But like many of Maggies almost-moments, it still deserves to be seen. Because sometimes, even the wrong outfit tells us something honest about who she is underneath it all.</p>
</div>
</div>
<!-- Section 5 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-1">
<responsive-image src="maggie-fashion-2.png" class="img-fluid" alt="Lace & Lager" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“She wore hope in the shape of a dress. And for a moment, she almost believed it would be enough.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Lace & Lager” The First Date Dress</h5>
<p>This was the one. The dress Maggie wore the night she finally let herself hope for something real, and got two pints of beer tipped over her for the trouble. I designed it around contradiction: soft lace sleeves clinging like whispered promises, paired with a defiant red skirt that billowed like a dare. It wasnt subtle. It wasnt supposed to be. It was Maggie stepping into the world not as someone surviving, but as someone choosing to be seen.</p>
<p>The top was reworked from a more elegant concept, too much for Ricardos, but perfect once grounded by the rough texture and boldness of that crumpled scarlet skirt. I loved that about her. How she blended grace with grit. The result was vulnerable and fearless all at once, which is probably why the moment hurt so much when it all went wrong.</p>
<p>She looked stunning that night. I remember writing that scene with a tightness in my chest, knowing exactly how much that outfit meant to her, not just as a creation, but as a risk. And seeing it ruined, soaked in lager and shame, broke my heart. But that was the point. This dress, like Maggie, deserved better. And eventually… she gets it.</p>
</div>
</div>
<!-- Section 6 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-2">
<responsive-image src="maggie-fashion-13.png" class="img-fluid" alt="Velvet Resolve" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“It made her feel powerful… but not like herself.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Velvet Resolve” The One That Stayed Behind</h5>
<p>This was a contender, a serious one. There was a moment when I imagined Maggie standing at the top of the stairs in this, every line of the dress perfectly composed, every eye in the restaurant turning to look. The plunging black velvet bodice, the way it folded into that crimson skirt… it was elegance incarnate. Mature. Commanding. And, in the end, just a little too much.</p>
<p>Because Maggie, for all her power, wasnt trying to impress that night, not with poise. She wanted to feel beautiful, yes, but she also wanted to feel *real*. To be herself, raw edges and all. This dress was breathtaking, but it was armour. And what she needed then was something that breathed with her, not something that held her still.</p>
<p>But I still keep it here, in the scrapbook. Because this was the version of Maggie who might have walked into that meal pretending she wasnt scared. The one who hid every bruise behind glamour. It didnt make it to the page, but it came very close.</p>
</div>
</div>
<!-- Section 5 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-1">
<responsive-image src="maggie-fashion.png" class="img-fluid" alt="Threadbare Ghost" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“She didnt need a scene to wear this. Just a window, and a reason to breathe.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Threadbare Ghosts” The Dress Without a Scene</h5>
<p>This one never had a chapter. No nightclub. No first date. No dramatic spill or kiss behind a curtain. It wasnt made for anything, and maybe thats why I love it. Because sometimes, Maggie just exists… not as a character in motion, but as a feeling. A breath. A girl wrapped in sunlight and silence, not trying to fight or impress or survive, just being. And this is what that moment looked like in my head.</p>
<p>The bodice is intricate, almost antique, like something stolen from a forgotten theatre. Lace, delicate and curling like memory. Faint threads of rust red and soft bone hues bleeding into the fabric, as if it once knew passion and never quite let go. She looks like something out of time. Something haunting and utterly alive. And thats the magic of it, she doesnt need to move to hold you. She just needs to look up, like this, and youre caught.</p>
<p>I never found the right place to write this dress in. But I never let it go, either. It stayed on my desk, on a scrap of paper, next to notes that never became dialogue. Because some images dont need stories. They *are* the story… just quietly, beautifully, waiting.</p>
</div>
</div>
<!-- Section 6 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-2">
<responsive-image src="maggie-fashion-14.png" class="img-fluid" alt="Summer Soft" display-width-percentage="50"></responsive-image>
<blockquote class="text-black" style="font-style: italic; margin-top: 1em;">
“She wore it first. Beth made it hers. But what stitched them together was never fabric.”
</blockquote>
</div>
<div class="scrapbook-text">
<h5>“Summer Soft” The Outfit They Shared</h5>
<p>This outfit was never meant to be a showstopper. It wasnt fire or lace or velvet. It was light, deliberately so. The white cotton skirt, simple and sun-washed, the top just delicate enough to feel like a whisper. This was the first outfit Maggie wore to Ricardos, when she needed to feel both presentable and herself. It wasnt designed to turn heads… and yet it did, quietly, effortlessly. She wore it with that rare kind of grace that doesnt try, and so becomes unforgettable.</p>
<p>Later, she lent it to Beth, and thats when it truly earned its place in the story. Because clothes carry energy. They hold memory. And in that moment, Maggie wasnt just lending an outfit. She was offering safety, trust, sisterhood before either of them even knew the word for it. Beth, wrapped in Maggies confidence, stepping into her own space, her own choices, it made me cry when I wrote it. Still does.</p>
<p>Its not the most elaborate design in the scrapbook, not by a long shot. But maybe thats what makes it so important. Because sometimes, what matters most isnt how it looks… but who it becomes part of.</p>
</div>
</div>
</div>
@section Meta {
<style>
.scrapbook-section {
margin-bottom: 4rem;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.scrapbook-image {
background: white;
padding: 10px 10px 30px 10px;
box-shadow: 2px 4px 12px rgba(0, 0, 0, 0.15);
border: 1px solid #ccc;
width: 100%;
max-width: 300px;
margin: 1rem;
transform: rotate(var(--angle));
}
.scrapbook-text {
flex: 1;
min-width: 250px;
margin: 1rem;
}
.rotate-1 {
--angle: -3deg;
}
.rotate-2 {
--angle: 2deg;
}
.rotate-3 {
--angle: -2deg;
}
.rotate-4 {
--angle: 3deg;
}
@@media (max-width: 768px) {
.scrapbook-section {
flex-direction: column;
}
.scrapbook-image {
margin-bottom: 1rem;
}
}
</style>
}

View File

@ -0,0 +1,217 @@

<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Extras">Extras</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Extras">Discovery</a></li>
<li class="breadcrumb-item active" aria-current="page">Discovery Scrap Book</li>
</ol>
</nav>
</div>
</div>
<div class="container">
<h1 class="mb-5 text-center">Discover Scrapbook</h1>
<p>
On this page I've included some of the images that helped inspire me to write The Alpha Flame: Discovery.
</p>
<p>
Some of them are fictional, generated by AI, others are real, both recent and archive photos.
</p>
<p>
I find that when I'm writing I like to imagine the scene. So having a visual guide helps me tremendously.
So I might, for example, ask AI to generate an image of a luxurious restaraunt. The I would look at the result
and tweak it, until what I was looking at matches what was in my imagination. I also find it useful to do the reverse.
I might write a description of a particular location, Beth's flat was one of them, and then feed that into AI to see
if it generated what I'd described. This was really useful because it helped me work out whether there was enough detail.
My thoughts were that if AI can draw what I've described, then I'm sure you as a reader will be able to imagine something
similar. Hopefully it's worked.
</p>
<!-- Section 1 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-1">
<responsive-image src="flyover-at-night.png" class="img-fluid" alt="The Rubery flyover at night time" display-width-percentage="50"></responsive-image>
</div>
<div class="scrapbook-text">
<h5>The Rubery Flyover</h5>
<p>
A number of scenes in The Alpha Flame: Discovery are set, or at least start here. The Rubery flyover carries the A38 Bristol Road
down to meet the M5. It's the main road in and out of the city from the South West. Quite why the floyover exists is something of
a mystery to me. Apart from allowing traffic to pass underneath it, past "Beth's Bench", it seems to serve no purpose. It doesn't
bridge any sort of gap in the landscape. Neither does it provide access to a higher ground further along.
</p>
<p>
Many years ago I used to live in this area and travelling underneath the flyover really gave me the creeps. As I describe in the book
there were often many unsavoury characters seated on the benches. And thre genuinely were women offering their bodies to whoever
happened to drive past.
</p>
</div>
</div>
<!-- Section 2 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-2">
<responsive-image src="beth-in-her-flat.png" class="img-fluid" alt="Beth in her flat" display-width-percentage="50"></responsive-image>
</div>
<div class="scrapbook-text">
<h5>Beth and Her Flat</h5>
<p>
In the beginning Beth's flat was even more depressing that it is described in the book. The idea of a sterotypical
early 1980s council flat was too hard to resist. However once I had developed her personality a little further it
became obvious that she would have a lot more pride in where she lived, even if she had no money.
</p>
<p>
In reality the block of flats that I put Beth in are only two storeys on top of a row of shops. But for the
purpose of the book I made them into one of the taller blocks that can be found all over the area.
</p>
</div>
</div>
<!-- Section 3 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-3">
<responsive-image src="rubery-hill-hospital.png" class="img-fluid" alt="Rubery Hill Hospital" display-width-percentage="50"></responsive-image>
</div>
<div class="scrapbook-text">
<h5>Rubery Hill Hospital</h5>
<p>
Now this place used to genuinely give me the creeps. It was built way back in the 1800s and as I say in the book,
was origonally known as "The City of Birmingham Lunatic Asylum". It was renamed many times over it's long life
but always had links to what we would call "mental health" these days. From what I have found out the only deviation
from this was during the war, when it was a hospital for injured soldiers.
</p>
</div>
</div>
<!-- Section 4 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-4">
<responsive-image src="maggie-in-her-jump-suit.png" class="img-fluid" alt="Maggie in Her Jumpsuit" display-width-percentage="50"></responsive-image>
</div>
<div class="scrapbook-text">
<h5>Maggie in Her Jumpsuit</h5>
<p>
So, the scene where Maggie goes to Limelight and walks across the dance floor to go and say hello to Zoe and Graham. Is this what you imagined?
I doubt it, but it was what was in my mind. The original description of this outfit went on for over a page, and I think you can see why.
Unfortuantely it got severaly cut in the edit. You're probably quite thankful for that!
</p>
<p>
But wouldn't you just love to wear it!
</p>
</div>
</div>
<!-- Section 5 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-1">
<responsive-image src="ricardos.png" class="img-fluid" alt="Ricardos" display-width-percentage="50"></responsive-image>
</div>
<div class="scrapbook-text">
<h5>Ricardo's</h5>
<p>
The extremely lavish Riscrod's restaraunt went through many changes, and evloved into something more luxurious every
single time. I'm not sure this image does it justice, but I hope by my descriptions you got the feeling of the sheer
opulance within it.
</p>
<p>
In reality Northfield never had any such restaraunt, it's simply not that sort of place. But it's nice to think that
it could have.
</p>
</div>
</div>
<!-- Section 6 -->
<div class="scrapbook-section flex-row-reverse">
<div class="scrapbook-image rotate-2">
<responsive-image src="beth-in-her-flat.png" class="img-fluid" alt="Beth in her flat" display-width-percentage="50"></responsive-image>
</div>
<div class="scrapbook-text">
<h5>Beth and Her Flat</h5>
<p>
In the beginning Beth's flat was even more depressing that it is described in the book. The idea of a sterotypical
early 1980s council flat was too hard to resist. However once I had developed her personality a little further it
became obvious that she would have a lot more pride in where she lived, even if she had no money.
</p>
<p>
In reality the block of flats that I put Beth in are only two storeys on top of a row of shops. But for the
purpose of the book I made them into one of the taller blocks that can be found all over the area.
</p>
</div>
</div>
<!-- Section 7 -->
<div class="scrapbook-section">
<div class="scrapbook-image rotate-3">
<responsive-image src="rubery-hill-hospital.png" class="img-fluid" alt="Rubery Hill Hospital" display-width-percentage="50"></responsive-image>
</div>
<div class="scrapbook-text">
<h5>Rubery Hill Hospital</h5>
<p>
Now this place used to genuinely give me the creeps. It was built way back in the 1800s and as I say in the book,
was origonally known as "The City of Birmingham Lunatic Asylum". It was renamed many times over it's long life
but always had links to what we would call "mental health" these days. From what I have found out the only deviation
from this was during the war, when it was a hospital for injured soldiers.
</p>
</div>
</div>
</div>
@section Meta {
<style>
.scrapbook-section {
margin-bottom: 4rem;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.scrapbook-image {
background: white;
padding: 10px 10px 30px 10px;
box-shadow: 2px 4px 12px rgba(0, 0, 0, 0.15);
border: 1px solid #ccc;
width: 100%;
max-width: 300px;
margin: 1rem;
transform: rotate(var(--angle));
}
.scrapbook-text {
flex: 1;
min-width: 250px;
margin: 1rem;
}
.rotate-1 {
--angle: -3deg;
}
.rotate-2 {
--angle: 2deg;
}
.rotate-3 {
--angle: -2deg;
}
.rotate-4 {
--angle: 3deg;
}
@@media (max-width: 768px) {
.scrapbook-section {
flex-direction: column;
}
.scrapbook-image {
margin-bottom: 1rem;
}
}
</style>
}

View File

@ -16,7 +16,7 @@
<div class="col-12"> <div class="col-12">
<div class="float-md-start w-md-50 p-3"> <div class="float-md-start w-md-50 p-3">
<figure> <figure>
<responsive-image src="catherine-lynwood-14.png" alt="Catherine Lynwood" class="img-fluid rounded-5 border border-3 border-dark shadow-lg" display-width-percentage="50"></responsive-image> <responsive-image src="catherine-lynwood-15.png" alt="Catherine Lynwood" class="img-fluid rounded-5 border border-3 border-dark shadow-lg" display-width-percentage="50"></responsive-image>
<figcaption>Catherin Lynwood</figcaption> <figcaption>Catherin Lynwood</figcaption>
</figure> </figure>
</div> </div>
@ -61,10 +61,10 @@
"@@context": "https://schema.org", "@@context": "https://schema.org",
"@@type": "Person", "@@type": "Person",
"name": "Catherine Lynwood", "name": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com/about-catherine-lynwood", "url": "https://www.catherinelynwood.com",
"description": "Learn more about Catherine Lynwood, author of *The Alpha Flame*, a novel featuring romance, mystery, and family secrets.",
"jobTitle": "Author", "jobTitle": "Author",
"knowsAbout": ["fiction writing", "mystery novels", "family drama"] "knowsAbout": ["womens fiction", "family secrets novels", "mystery"],
"knowsLanguage": "English"
} }
</script> </script>
} }

View File

@ -1,5 +1,5 @@
@{ @{
ViewData["Title"] = "Catherine Lynwood"; ViewData["Title"] = "The Alpha Flame";
} }
<div class="row"> <div class="row">
@ -11,38 +11,33 @@
</nav> </nav>
</div> </div>
</div> </div>
<div class="row">
<div class="col-md-6 text-center"> <!-- Hero Section -->
<responsive-image src="catherine-lynwood-11.png" alt="Catherine Lynwood" class="img-fluid rounded-5 border border-3 border-dark shadow-lg" display-width-percentage="50"></responsive-image> <div class="row align-items-center mb-5">
<div class="col-md-5 text-center">
<responsive-image src="the-alpha-flame-11.png" alt="The Alpha Flame: Discovery" class="img-fluid rounded-5 border border-3 border-dark shadow-lg" display-width-percentage="50"></responsive-image>
</div> </div>
<div class="col-md-7">
<div class="col-md-6"> <h1 class="display-5 fw-bold">The Alpha Flame: <span class="fw-light">Discovery</span></h1>
<header> <p class="lead fst-italic">Some girls survive. Others set the world on fire.</p>
<h1>Welcome to Catherine Lynwood's World</h1> <p>
</header> When Maggie Grant finds Beth, bruised, terrified, and alone, she has no idea the rescue will ignite a chain of secrets buried deep in her own past. Set in 1980s Britain, <em>The Alpha Flame: Discovery</em> is a story of sisterhood, survival, and the power of fire to both destroy and redeem.
</p>
<section> <div class="d-flex gap-3 flex-wrap">
<p>Step into the pages of <em><a class="link-dark fw-bold" asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></em>, where emotions burn brightly, secrets twist through each chapter, and powerful women shape their own destinies. As a debut novelist, Catherine Lynwood invites you to experience a story crafted with depth, grit, and heart—a journey that pulls you into the lives of characters who refuse to live within anyone elses lines.</p> <a href="/the-alpha-flame/discovery" class="btn btn-dark">Explore the Book</a>
</section> <a href="/the-alpha-flame/extras" class="btn btn-outline-dark">Unlock Extras</a>
<section>
<p>In <em><a class="link-dark fw-bold" asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></em>, readers will meet Maggie Grant, a woman whose fierce intelligence and subtle dominance lead her on a thrilling path through 1980s Britain. Set against a backdrop of mystery and romance, Maggies story delves into the complexities of family, the weight of secrets, and the power of self-discovery. From the streets of Birmingham to quiet English countrysides, Catherine weaves a narrative that is as provocative as it is poignant.</p>
</section>
<div class="text-center pb-4">
<a asp-controller="TheAlphaFlame" asp-action="Blog" class="btn btn-dark">Read The Alpha Flame Blog</a>
</div> </div>
<p class="mt-4">
<em>The Alpha Flame: Discovery</em>, writen by <a asp-controller="Home" asp-action="AboutCatherineLynwood" class="link-dark fw-semibold">Catherine Lynwood</a>, is the first in a powerful trilogy following the tangled lives of Maggie and Beth , two women bound by fate, fire, and secrets too dangerous to stay buried.
The journey continues in <strong>Reckoning</strong> (Spring 2026) and concludes with <strong>Redemption</strong> (Autumn 2026).
Learn more about the full trilogy on the <a asp-controller="TheAlphaFlame" asp-action="Index" class="link-dark fw-semibold">Alpha Flame series page</a>.
</p>
<section>
<p>Catherine writes with a keen sensitivity to the struggles and triumphs of women who navigate love, loyalty, and identity on their own terms. <em><a class="link-dark fw-bold" asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></em> is not simply a romance or a thriller; its an exploration of strength, vulnerability, and the desire to be fully seen and heard. Each chapter unfolds with rich detail, bringing the 1980s to life in a way that feels both timeless and deeply personal.</p>
</section>
<section>
<p>Whether youre here to discover more about Catherine's debut or to explore the upcoming projects shes hinted at, welcome. This is a space for stories that challenge convention and celebrate resilience. Follow along as Catherine Lynwood shares updates, reflections, and glimpses into the worlds and characters she is passionate about bringing to life.</p>
</section>
</div> </div>
</div> </div>
@section Meta { @section Meta {
<meta name="description" content="Explore the captivating world of Catherine Lynwoods *The Alpha Flame*, a powerful novel blending romance, mystery, and family secrets set in the 1980s. Follow twin sisters as they unravel hidden truths and face emotional challenges. Discover more about Catherine Lynwoods storytelling and insights on the official website."> <meta name="description" content="Explore the captivating world of Catherine Lynwoods *The Alpha Flame*, a powerful novel blending romance, mystery, and family secrets set in the 1980s. Follow twin sisters as they unravel hidden truths and face emotional challenges. Discover more about Catherine Lynwoods storytelling and insights on the official website.">
@ -75,4 +70,53 @@
"knowsLanguage": "English" "knowsLanguage": "English"
} }
</script> </script>
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "Book",
"name": "The Alpha Flame: Discovery",
"alternateName": "The Alpha Flame Book 1",
"author": {
"@@type": "Person",
"name": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com"
},
"publisher": {
"@@type": "Organization",
"name": "Catherine Lynwood"
},
"datePublished": "2025-08-21",
"description": "The Alpha Flame: Discovery is a powerful, character-driven novel set in 1983 Birmingham, following Maggie Grant and Beth—two young women separated by fate, reunited by truth, and bound by secrets. As past traumas resurface and danger closes in, their journey through survival, sisterhood, and redemption begins.",
"genre": "Women's Fiction, Mystery, Contemporary Historical",
"inLanguage": "en-GB",
"url": "https://www.catherinelynwood.com/the-alpha-flame/discovery",
"workExample": [
{
"@@type": "Book",
"bookFormat": "https://schema.org/Hardcover",
"isbn": "978-1-0682258-0-2",
"name": "The Alpha Flame: Discovery Hardback"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/Paperback",
"isbn": "978-1-0682258-1-9",
"name": "The Alpha Flame: Discovery Softback"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/Paperback",
"isbn": "978-1-0682258-2-6",
"name": "The Alpha Flame: Discovery Amazon Edition"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/EBook",
"isbn": "978-1-0682258-3-3",
"name": "The Alpha Flame: Discovery eBook"
}
]
}
</script>
} }

View File

@ -0,0 +1,55 @@
<section id="privacy-mailing-list" class="container mt-5">
<h2>Mailing List and Reader Access Data</h2>
<p>
We respect your privacy and are committed to protecting your personal data. This section explains how we handle the information you may provide when accessing bonus content on this site.
</p>
<h4>What We Collect</h4>
<p>
When you enter a word from your physical copy of a Catherine Lynwood book to unlock extras, we store a small amount of session data to determine what content you can access. This includes:
</p>
<ul>
<li>Your access level (based on the edition of the book)</li>
<li>The book(s) you are entitled to access</li>
</ul>
<p>
When you choose to join our mailing list, we may also collect the following:
</p>
<ul>
<li>Your email address (optional)</li>
<li>
Your selected communication preferences:
<ul>
<li>Updates about <em>The Alpha Flame</em> trilogy</li>
<li>Access to bonus material and digital extras</li>
<li>News about future books by Catherine Lynwood</li>
</ul>
</li>
</ul>
<p>
A single cookie (<code>MailingListPrompted=true</code>) is set to ensure we only ask once.
</p>
<h4>How We Use Your Information</h4>
<ul>
<li>To give you access to content appropriate for your book and edition</li>
<li>To email you with the types of updates you selected, and nothing else</li>
<li>To avoid re-prompting you unnecessarily for mailing list opt-in</li>
</ul>
<p>
We do <strong>not</strong> use your data for advertising, do <strong>not</strong> sell your data, and do <strong>not</strong> share your email address with third parties.
</p>
<h4>Your Rights</h4>
<ul>
<li>You can unsubscribe from emails at any time using the link provided in each message.</li>
<li>You can request to view or delete the information we hold about you by contacting us directly.</li>
<li>We retain minimal data only as necessary to manage access and communications.</li>
</ul>
<p>
For more information about your rights under the General Data Protection Regulation (GDPR), please visit
<a href="https://www.gov.uk/data-protection" target="_blank" rel="noopener noreferrer">www.gov.uk/data-protection</a>.
</p>
</section>

View File

@ -0,0 +1,163 @@
@{
ViewData["Title"] = "Catherine Lynwood Publishing";
}
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Publishing</li>
</ol>
</nav>
</div>
</div>
<div class="row mb-4">
<div class="col-12">
<h1 class="display-5 mb-3">Catherine Lynwood Publishing</h1>
<p class="lead">The official imprint of author Catherine Lynwood</p>
</div>
</div>
<div class="row">
<div class="col-md-10 col-lg-8">
<section class="mb-5">
<h2 class="h4">About the Imprint</h2>
<p>Catherine Lynwood Publishing is the registered trading name under which Catherine Lynwood independently publishes her written works. Established in the United Kingdom as a sole trader business, this imprint allows full control over every aspect of the creative and publishing process.</p>
<p>From editing and layout to cover design and distribution, each book released under this imprint is crafted with care, passion, and an unwavering focus on quality storytelling.</p>
</section>
<section class="mb-5">
<h2 class="h4">What We Do</h2>
<ul>
<li>Publish and manage the <strong>Alpha Flame Trilogy</strong> and future titles</li>
<li>Oversee all design, layout, and editorial decisions</li>
<li>Register and manage ISBNs and metadata</li>
<li>Coordinate print and eBook distribution via IngramSpark, Amazon, and other platforms</li>
<li>Offer exclusive editions and extras via this website</li>
</ul>
</section>
<section class="mb-5">
<h2 class="h4">Current Titles</h2>
<p><strong>The Alpha Flame: Discovery</strong> (Book One of the Alpha Flame Trilogy)</p>
<ul>
<li>Available in hardback, paperback, eBook, and Amazon-exclusive editions</li>
<li>More titles coming soon</li>
</ul>
</section>
<section class="mb-5">
<h2 class="h4">Publishing Philosophy</h2>
<p>At Catherine Lynwood Publishing, we believe that independent publishing can offer the same exceptional quality as traditional houses, with greater creative freedom. Every detail matters: from the emotional weight of the story to the typography, layout, and binding.</p>
<p>Our goal is to deliver books that not only tell powerful stories but look and feel beautiful in your hands.</p>
</section>
<section class="mb-5">
<h2 class="h4">For Retailers & Libraries</h2>
<p>All titles under this imprint are registered with ISBNs and distributed through reputable global networks. If you are a bookshop, library, or distributor and would like to stock our titles or learn more about upcoming releases, please get in touch.</p>
<p><strong>Contact:</strong> <a href="mailto:catherine@catherinelynwood.com">catherine@catherinelynwood.com</a></p>
</section>
<section>
<h2 class="h4">Legal Information</h2>
<ul class="list-unstyled">
<li><strong>Trading Name:</strong> Catherine Lynwood Publishing</li>
<li><strong>Business Type:</strong> Sole Trader</li>
<li><strong>Established:</strong> 2025</li>
<li><strong>Country:</strong> United Kingdom</li>
</ul>
</section>
</div>
</div>
@section Meta{
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "Organization",
"name": "Catherine Lynwood Publishing",
"alternateName": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com/publishing",
"logo": "https://www.catherinelynwood.com/images/logo.png",
"description": "Catherine Lynwood Publishing is the registered sole trader imprint of author Catherine Lynwood, responsible for the publication and distribution of the Alpha Flame Trilogy and future works.",
"founder": {
"@@type": "Person",
"name": "Catherine Lynwood",
"sameAs": [
"https://www.catherinelynwood.com"
]
},
"foundingDate": "2025",
"location": {
"@@type": "Place",
"address": {
"@@type": "PostalAddress",
"addressCountry": "UK"
}
},
"publishingPrinciples": "https://www.catherinelynwood.com/publishing#philosophy",
"makesOffer": {
"@@type": "OfferCatalog",
"name": "Published Titles",
"itemListElement": [
{
"@@type": "Product",
"name": "The Alpha Flame: Discovery (Hardback)",
"productID": "ISBN:978-1-0682258-0-2",
"description": "Hardback edition of Book One in the Alpha Flame Trilogy.",
"url": "https://www.catherinelynwood.com/the-alpha-flame",
"offers": {
"@@type": "Offer",
"availability": "https://schema.org/InStock",
"priceCurrency": "GBP"
}
},
{
"@@type": "Product",
"name": "The Alpha Flame: Discovery (Paperback)",
"productID": "ISBN:978-1-0682258-1-9",
"description": "Paperback edition of Book One in the Alpha Flame Trilogy.",
"url": "https://www.catherinelynwood.com/the-alpha-flame",
"offers": {
"@@type": "Offer",
"availability": "https://schema.org/InStock",
"priceCurrency": "GBP"
}
},
{
"@@type": "Product",
"name": "The Alpha Flame: Discovery (Amazon Edition)",
"productID": "ISBN:978-1-0682258-2-6",
"description": "Amazon-exclusive edition of Book One in the Alpha Flame Trilogy.",
"url": "https://www.amazon.co.uk/dp/B0D3T5XYTG", // Replace with your actual Amazon product URL
"offers": {
"@@type": "Offer",
"availability": "https://schema.org/InStock",
"priceCurrency": "GBP"
}
},
{
"@@type": "Product",
"name": "The Alpha Flame: Discovery (eBook)",
"productID": "ISBN:978-1-0682258-3-3",
"description": "eBook edition of Book One in the Alpha Flame Trilogy.",
"url": "https://www.catherinelynwood.com/the-alpha-flame",
"offers": {
"@@type": "Offer",
"availability": "https://schema.org/InStock",
"priceCurrency": "GBP"
}
}
]
},
"sameAs": [
"https://www.catherinelynwood.com",
"https://www.amazon.co.uk/dp/B0D3T5XYTG" // Confirm or add additional relevant links
]
}
</script>
}

View File

@ -0,0 +1,17 @@
@{
ViewData["Title"] = "Access Denied";
}
<div class="container mt-5 text-center">
<h2 class="text-danger mb-3">Access Denied</h2>
<p class="lead">Sorry, you dont have permission to view this content.</p>
<p>
If you believe this is an error, please <a href="/Access/Prompt">verify your book again</a>.<br />
Or return to the <a href="/Extras">Extras home page</a>.
</p>
<div class="mt-4">
<img src="/images/lock.png" alt="Access Denied" style="max-width:150px;" />
</div>
</div>

View File

@ -48,7 +48,7 @@
<h2>Leave a Comment</h2> <h2>Leave a Comment</h2>
In invite you to leave comments regarding this blog post. As you can see I ask that you give me your name and email address, as well as your age and sex. In invite you to leave comments regarding this blog post. As you can see I ask that you give me your name and email address, as well as your age and sex.
This is so I can better understand my audience and tailor my content to suit your needs. I will never share your information with anyone else. I look forward to hearing from you. This is so I can better understand my audience and tailor my content to suit your needs. I will never share your information with anyone else. I look forward to hearing from you.
Please note that I may email you and ask for a reply before publishng your comment. This is to ensure that I am not publishing spam comments. Please note that I may email you and ask for a reply before publishing your comment. This is to ensure that I am not publishing spam comments.
</div> </div>
<div class="col-12 text-dark"> <div class="col-12 text-dark">
<div asp-validation-summary="ModelOnly" class="text-danger"></div> <div asp-validation-summary="ModelOnly" class="text-danger"></div>
@ -71,10 +71,13 @@
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<select asp-for="Age" name="Age" class="form-select" aria-label="Select your age"> <select asp-for="Age" name="Age" class="form-select" aria-label="Select your age">
<option value="" selected>Select your age</option> <option value="" selected>Select your age</option>
@for (var age = 18; age <= 120; age++) <option value="18-24">1824</option>
{ <option value="25-34">2534</option>
<option value="@age">@age</option> <option value="35-44">3544</option>
}) <option value="45-54">4554</option>
<option value="55-64">5564</option>
<option value="65+">65+</option>
<option value="0">Prefer not to say</option>
</select> </select>
<label asp-for="Age"></label> <label asp-for="Age"></label>
<span asp-validation-for="Age" class="text-danger"></span> <span asp-validation-for="Age" class="text-danger"></span>
@ -105,7 +108,7 @@
<div class="alert alert-info"> <div class="alert alert-info">
<h3 class="alert-heading">Please Note</h3> <h3 class="alert-heading">Please Note</h3>
<p> <p>
By posting a comment, you agree to allow us to contact you regarding your comment. Additionally, you consent to receive occasional updates, blog posts, and news about our latest content and book releases. You may opt out of these communications at any time. By posting a comment, you agree to allow us to contact you regarding your comment.
</p> </p>
<div class="form-check pb-3"> <div class="form-check pb-3">
<input type="checkbox" class="form-check-input" id="agreeTerms"> <input type="checkbox" class="form-check-input" id="agreeTerms">

View File

@ -9,6 +9,20 @@
<link rel="stylesheet" href="~/css/fontawesome.min.css" asp-append-version="true" /> <link rel="stylesheet" href="~/css/fontawesome.min.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/brands.min.css" asp-append-version="true" /> <link rel="stylesheet" href="~/css/brands.min.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/duotone.min.css" asp-append-version="true" /> <link rel="stylesheet" href="~/css/duotone.min.css" asp-append-version="true" />
<link rel="stylesheet" href="https://cdn.plyr.io/3.7.2/plyr.css" />
<style>
.plyr--audio .plyr__controls {
background-color: transparent !important; /* or set your page colour */
box-shadow: none !important; /* optional: remove shadow */
border-radius: 0; /* optional: adjust corners */
}
.plyr--audio {
background-color: transparent !important; /* background of the whole player */
}
</style>
<link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png"> <link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png"> <link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
@ -66,7 +80,7 @@
The Alpha Flame The Alpha Flame
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li class="py-2"><a class="dropdown-item" asp-controller="TheAlphaFlame" asp-action="Index">Book Previews</a></li> <li class="py-2"><a class="dropdown-item" asp-controller="TheAlphaFlame" asp-action="Index">The Trilogy</a></li>
@* <li><hr class="dropdown-divider"></li> *@ @* <li><hr class="dropdown-divider"></li> *@
<li class="py-2"><a class="dropdown-item" asp-controller="TheAlphaFlame" asp-action="Characters">Meet the Characters</a></li> <li class="py-2"><a class="dropdown-item" asp-controller="TheAlphaFlame" asp-action="Characters">Meet the Characters</a></li>
</ul> </ul>
@ -87,18 +101,21 @@
</div> <!-- End of content wrapper --> </div> <!-- End of content wrapper -->
<footer class="border-top border-2 border-primary footer bg-dark"> <footer class="border-top border-2 border-primary footer bg-dark py-3">
<div class="container"> <div class="container">
<div class="row justify-content-center align-items-center" style="height: 140px;"> <div class="row justify-content-center align-items-center" >
<div class="col-12"> <div class="col-md-4 text-center order-md-2">
<social-media-share title="Catherine Lynwood Blog" url="@Context.Request.Path" class="text-center m-3"></social-media-share> <social-media-share title="Catherine Lynwood Blog" url="@Context.Request.Path" class="text-center m-3"></social-media-share>
</div>
<div class="col-12 text-center">
<a class="text-light" asp-area="" asp-controller="Home" asp-action="ContactCatherine">Contact Catherine</a>
</div>
<div class="col-12 text-center text-light">
&copy; 2024 - Catherine Lynwood &copy; 2024 - Catherine Lynwood
</div> </div>
<div class="col-md-4 text-center order-md-1">
<a class="text-light" asp-area="" asp-controller="Home" asp-action="ContactCatherine">Contact Catherine</a>
</div>
<div class="col-md-4 text-center order-md-3">
<a class="text-light" asp-area="" asp-controller="Publishing" asp-action="Index">Catherine Lynwood Publishing</a>
</div>
</div> </div>
</div> </div>
</footer> </footer>
@ -108,6 +125,10 @@
<script src="~/js/site.js" asp-append-version="true"></script> <script src="~/js/site.js" asp-append-version="true"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script> <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script> <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script src="https://cdn.plyr.io/3.7.2/plyr.polyfilled.js"></script>
<script>
const player = new Plyr('audio');
</script>
@RenderSection("Scripts", required: false) @RenderSection("Scripts", required: false)
</body> </body>

View File

@ -25,6 +25,15 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<figure class="figure w-sm-50 p-3">
<div class="figure-img ratio ratio-16x9 rounded-5 border border-dark border-3 bg-dark">
<video controls="controls" autoplay="autoplay" poster="/images/Synopsis-Beth.png" class="rounded-5">
<source src="~/videos/Synopsis-Beth.mp4" type="video/mp4" />
</video>
</div>
<figcaption class="figure-caption">Watch Beth tell you about her story.</figcaption>
</figure>
<div class="float-sm-start w-sm-50 p-3"> <div class="float-sm-start w-sm-50 p-3">
<div id="carouselControls" class="carousel slide" data-bs-ride="carousel"> <div id="carouselControls" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner"> <div class="carousel-inner">
@ -57,6 +66,9 @@
</button> </button>
</div> </div>
</div> </div>
<h2>Beth Fletcher</h2> <h2>Beth Fletcher</h2>
<p>I love the character of Beth. To me she's the most interesting of them all. Her harrowing back story and life of poverty and squaller shapes her character, yet through it all she still manages to maintain her personal standards.'</p> <p>I love the character of Beth. To me she's the most interesting of them all. Her harrowing back story and life of poverty and squaller shapes her character, yet through it all she still manages to maintain her personal standards.'</p>
<h2 class="mb-3">Overview</h2> <h2 class="mb-3">Overview</h2>
@ -123,6 +135,19 @@
<meta name="author" content="Catherine Lynwood"> <meta name="author" content="Catherine Lynwood">
<meta name="twitter:card" content="player">
<meta name="twitter:site" content="@@CathLynwood">
<meta name="twitter:title" content="Beth Fletcher | The Alpha Flame">
<meta name="twitter:description" content="Dive into the captivating world of The Alpha Flame and meet Maggie Grant, a character full of depth and intrigue.">
<meta name="twitter:image" content="https://www.catherinelynwood.com/images/Synopsis-Beth.png">
<meta name="twitter:player" content="https://www.catherinelynwood.com/videos/Synopsis-Beth.mp4">
<meta name="twitter:player:width" content="640">
<meta name="twitter:player:height" content="360">
<meta name="twitter:player:stream" content="https://www.catherinelynwood.com/videos/Synopsis-Beth.mp4">
<meta name="twitter:player:stream:content_type" content="video/mp4">
<script type="application/ld+json"> <script type="application/ld+json">
{ {
"@@context": "https://schema.org", "@@context": "https://schema.org",

View File

@ -8,6 +8,7 @@
<ol class="breadcrumb"> <ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li> <li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li> <li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="DIscovery">Discovery</a></li>
<li class="breadcrumb-item active" aria-current="page">Chapter 1 Excerpt</li> <li class="breadcrumb-item active" aria-current="page">Chapter 1 Excerpt</li>
</ol> </ol>
</nav> </nav>
@ -27,20 +28,28 @@
<div class="row gx-5"> <div class="row gx-5">
<!-- Scene Image --> <!-- Scene Image -->
<div class="col-lg-5 mb-4 mb-lg-0"> <div class="col-lg-5 mb-4 mb-lg-0">
<responsive-image src="beth-12.png" alt="Scene from Beth's story" class="img-fluid rounded-5 border border-3 border-dark shadow-lg" display-width-percentage="50"></responsive-image> <responsive-image src="beth-stood-in-bathroom.png" alt="Scene from Beth's story" class="img-fluid rounded-5 border border-3 border-dark shadow-lg" display-width-percentage="50"></responsive-image>
</div> </div>
<!-- Audio and Text --> <!-- Audio and Text -->
<div class="col-lg-7"> <div class="col-lg-7">
<div class="bg-white rounded-5 border border-3 border-dark shadow-lg p-3"> <div class="bg-white rounded-5 border border-3 border-dark shadow-lg p-3">
<div class="ratio ratio-16x9">
<video controls="controls" poster="/images/Chapter-1.png" class="rounded-5">
<source src="~/videos/Chapter-1-preview.mp4" type="video/mp4"/>
</video>
</div>
<!-- Audio Player --> <!-- Audio Player -->
<div class="audio-player text-center"> <div class="audio-player text-center">
<audio controls> <audio controls>
<source src="/audio/chapter-1-beth-excerpt.mp3" type="audio/mpeg"> <source src="/audio/the-alpha-flame-discovery-chapter-1.mp3" type="audio/mpeg">
Your browser does not support the audio element. Your browser does not support the audio element.
</audio> </audio>
<p class="text-center text-muted small">
Listen to Beth narrating chapter 1 - Drowning in Silence.
</p>
</div> </div>
<!-- Text Content --> <!-- Text Content -->
<div class="chapter-text"> <div class="chapter-text">
<p class="chapter-title">Drowning in Silence - Beth</p> <p class="chapter-title">Drowning in Silence - Beth</p>
@ -88,9 +97,57 @@
twitter-player-width="480" twitter-player-width="480"
twitter-player-height="80" /> twitter-player-height="80" />
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "Chapter",
"name": "Chapter 1: Drowning in Silence Beth",
"url": "https://www.catherinelynwood.com/the-alpha-flame/chapters/chapter-1-beth",
"description": "Beth returns home to a haunting silence, discovering her mother lifeless in the bath. This moment shatters her world, leaving her feeling utterly alone.",
"position": 1,
"inLanguage": "en-GB",
"isPartOf": {
"@@type": "Book",
"name": "The Alpha Flame: Discovery",
"author": {
"@@type": "Person",
"name": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com"
},
"publisher": {
"@@type": "Organization",
"name": "Catherine Lynwood"
},
"inLanguage": "en-GB",
"workExample": [
{
"@@type": "Book",
"bookFormat": "https://schema.org/Hardcover",
"isbn": "978-1-0682258-0-2",
"name": "The Alpha Flame: Discovery Hardback"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/Paperback",
"isbn": "978-1-0682258-1-9",
"name": "The Alpha Flame: Discovery Softback"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/Paperback",
"isbn": "978-1-0682258-2-6",
"name": "The Alpha Flame: Discovery Amazon Edition"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/EBook",
"isbn": "978-1-0682258-3-3",
"name": "The Alpha Flame: Discovery eBook"
}
]
}
}
</script>
} }

View File

@ -8,6 +8,7 @@
<ol class="breadcrumb"> <ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li> <li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li> <li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="DIscovery">Discovery</a></li>
<li class="breadcrumb-item active" aria-current="page">Chapter 2 Excerpt</li> <li class="breadcrumb-item active" aria-current="page">Chapter 2 Excerpt</li>
</ol> </ol>
</nav> </nav>
@ -37,9 +38,12 @@
<!-- Audio Player --> <!-- Audio Player -->
<div class="audio-player text-center"> <div class="audio-player text-center">
<audio controls> <audio controls>
<source src="/audio/chapter-2-maggie-excerpt.mp3" type="audio/mpeg"> <source src="/audio/the-alpha-flame-discovery-chapter-2.mp3" type="audio/mpeg">
Your browser does not support the audio element. Your browser does not support the audio element.
</audio> </audio>
<p class="text-center text-muted small">
Listen to Maggie narrating Chapter 2 - The Last Lesson,
</p>
</div> </div>
@ -96,5 +100,56 @@
twitter-player-width="480" twitter-player-width="480"
twitter-player-height="80" /> twitter-player-height="80" />
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "Chapter",
"name": "Chapter 2: The Last Lesson Maggie",
"url": "https://www.catherinelynwood.com/the-alpha-flame/chapters/chapter-2-maggie",
"description": "Maggie Grant bursts onto the page with wit, confidence, and a fiery spirit. As she faces challenges at college and flirts with independence, her strength and secrets begin to unfold.",
"position": 2,
"inLanguage": "en-GB",
"isPartOf": {
"@@type": "Book",
"name": "The Alpha Flame: Discovery",
"author": {
"@@type": "Person",
"name": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com"
},
"publisher": {
"@@type": "Organization",
"name": "Catherine Lynwood"
},
"inLanguage": "en-GB",
"workExample": [
{
"@@type": "Book",
"bookFormat": "https://schema.org/Hardcover",
"isbn": "978-1-0682258-0-2",
"name": "The Alpha Flame: Discovery Hardback"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/Paperback",
"isbn": "978-1-0682258-1-9",
"name": "The Alpha Flame: Discovery Softback"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/Paperback",
"isbn": "978-1-0682258-2-6",
"name": "The Alpha Flame: Discovery Amazon Edition"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/EBook",
"isbn": "978-1-0682258-3-3",
"name": "The Alpha Flame: Discovery eBook"
}
]
}
}
</script>
} }

View File

@ -0,0 +1,230 @@
@{
ViewData["Title"] = "The Alpha Flame: Discovery";
}
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item active" aria-current="page"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li>
<li class="breadcrumb-item active" aria-current="page">Discovery</li>
</ol>
</nav>
</div>
</div>
<!-- Specific Row for Book Cover and Synopsis -->
<div class="row">
<!-- Book Cover Section -->
<div class="col-md-4">
<section id="book-cover">
<div class="card character-card" id="cover-card">
<responsive-image src="the-alpha-flame-11.png" class="card-img-top" alt="The Alpha Flame Cover" display-width-percentage="50"></responsive-image>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">The Front Cover</h3>
<p class="card-text">This is the final front cover of The Alpha Flame: Discovery. It features Maggie stood outside the derelict Rubery Hill Hospital.</p>
</div>
</div>
</section>
</div>
<!-- Synopsis Section -->
<div class="col-md-8">
<section id="synopsis">
<div class="card character-card" id="synopsis-card">
<div class="card-header">
<h1>The Alpha Flame</h1>
</div>
<div class="card-body bg-light" id="synopsis-body">
<div class="row align-items-center">
<div class="col-2">
<responsive-image src="catherine-lynwood-16.png" class="img-fluid rounded-circle" alt="Catherine Lynwood" display-width-percentage="50"></responsive-image>
</div>
<div class="col-10">
<!-- Audio Section -->
<div class="audio-player text-center">
<audio id="player">
<source src="/audio/the-alpha-flame-discovery-synopsis.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
</div>
<p class="text-center text-muted small">
Listen to Catherine telling you about The Alpha Flame: Discovery
</p>
</div>
</div>
<div class="row">
<div class="col-12">
<div id="buy-now" class="my-4">
<a id="amazonLink" href="https://www.amazon.com/dp/B0FBS427VD" target="_blank" class="btn btn-dark">
Buy on Amazon
</a>
<p id="geoNote" class="text-muted small mt-2">Also available on your local Amazon store.</p>
</div>
</div>
</div>
<!-- Synopsis Content -->
<h3 class="card-title">Synopsis</h3>
<p class="card-text">The Alpha Flame is an unflinching and deeply emotional story of resilience, love, and survival, set against the vibrant yet tumultuous backdrop of 1983. Through the intersecting lives of two heroines, it delves into the extremes of human suffering and the boundless power of the human spirit to endure, adapt, and rise.</p>
<p class="card-text">For Beth, the world is a cold and unforgiving place. Devastation strikes in a single moment, leaving her isolated, shattered, and vulnerable. Alone in the bleak shadows of a city that offers neither refuge nor redemption, she is forced to navigate a relentless cycle of desperation and despair. Every step of her journey tests the limits of her endurance, pushing her into harrowing situations where survival feels like a hollow victory. Beths existence is marked by loss, betrayal, and an almost suffocating loneliness that threatens to consume her entirely. Yet, even in the darkest corners of her ordeal, a fragile ember of defiance smoulders within her, a quiet, stubborn refusal to let the world destroy her completely.</p>
<p class="card-text">Maggie, by contrast, is a force of nature, a woman who thrives on her unshakable drive and an unrelenting belief in her own power. Behind her fiery red hair and disarming charm lies a storm of determination and ferocity. Maggie doesnt just live; she races through life, fuelled by a need for speed and the thrill of freedom. Her Triumph TR6 isnt just a car; its an extension of her spirit, sleek, powerful, and unapologetically bold. On the open road, with the engine roaring and the world blurring past her, she feels invincible. But Maggies intensity doesnt stop at the wheel. Her relationships burn just as brightly. As a lover, she is dominant, passionate, and unafraid to embrace her darker desires. While fiercely loving and loyal, Maggie is also formidable; crossing her isnt a mistake anyone makes twice.</p>
<p class="card-text">When fate brings Beth and Maggie together, their connection is explosive, a union of two polar opposites that burns with both tenderness and raw power. For Beth, Maggie represents a lifeline, a reminder that love and trust still exist, even in a world that has betrayed her at every turn. For Maggie, Beth awakens a fierce protectiveness and vulnerability shes rarely allowed herself to feel. Together, they ignite a flame that challenges them to confront their own fears, desires, and limitations.</p>
<p class="card-text">Set against the kaleidoscope of 1983, where synthesised anthems provide a pulsing soundtrack and the streets are alive with the bold styles and rebellious energy of the decade, their story unfolds in a city teeming with danger and intrigue. From high-speed chases along winding roads to dimly lit clubs and desolate alleyways, the heroines journey is a visceral exploration of survival and freedom. The neon haze of the era contrasts sharply with the stark realities they face, painting a vivid picture of a world where strength and vulnerability coexist.</p>
<p class="card-text">As secrets surface and danger tightens its grip, Beth and Maggie must confront not only the challenges around them but the truths within themselves. Their bond is tested by betrayal, desire, and the shadows of their pasts, but through it all, their flame burns brighter, illuminating their courage and the unbreakable spirit of two heroines determined to rewrite their fates.</p>
<p class="card-text">At its heart, The Alpha Flame is a story of survival, passion, and empowerment. It explores the devastating lows and triumphant highs of life with unflinching honesty, capturing the raw power of human connection against the gritty, vibrant backdrop of an unforgettable era. With its blend of drama, intensity, and unapologetic emotion, this is a story that will leave its mark long after the final frame.</p>
</div>
</div>
</section>
</div>
</div>
<!-- Chapter Previews Section -->
<section id="chapters" class="mt-4">
<h2>Chapter Previews</h2>
<div class="row">
<div class="col-md-4 mb-4">
<div class="card h-100 character-card">
<a asp-action="Chapter1">
<responsive-image src="beth-stood-in-bathroom.png" class="card-img-top" alt="Beth's Bathroom" display-width-percentage="50"></responsive-image>
</a>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">Chapter 1: Drowning in Silence - Beth</h3>
<p class="card-text">Beth returns home to find her mother lifeless in the bath...</p>
<div class="text-end"><a asp-action="Chapter1" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card h-100 character-card">
<a asp-action="Chapter2">
<responsive-image src="maggie-with-her-tr6-2.png" class="fit-image" alt="Maggie With Her TR6" display-width-percentage="50"></responsive-image>
</a>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">Chapter 2: The Last Lesson - Maggie</h3>
<p class="card-text">On Christmas Eve, Maggie nervously heads out for her driving test...</p>
<div class="text-end"><a asp-action="Chapter2" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card h-100 character-card">
<a asp-action="Characters">
<responsive-image src="discovery-epilogue.png" class="fit-image" alt="Maggie Grant, The Alpha Flame" display-width-percentage="50"></responsive-image>
</a>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">Meet the Characters</h3>
<p class="card-text">Dive into the vibrant world of The Alpha Flame and discover the unforgettable cast of characters that bring this story to life.</p>
<p class="card-text">Get to know Maggie, the fiery and magnetic heart of the tale, and Beth, whose troubled past contrasts with her unyielding strength. Meet Rosie, Maggie's best friend, who brings warmth and humor to every scene, and Rebecca, a steady presence with a hidden depth.</p>
<p class="card-text">Explore the mind of Rob, the gadget-obsessed photographer whose quiet determination matches his deep connection to Maggie. Then theres Zoe, the sharp-witted ex-policewoman whos full of surprises.</p>
<div class="text-end"><a asp-action="Characters" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
</div>
</section>
@section Scripts {
<script>
window.addEventListener("load", function () {
const coverCard = document.getElementById("cover-card");
const synopsisCard = document.getElementById("synopsis-card");
const synopsisBody = document.getElementById("synopsis-body");
if (coverCard && synopsisCard && synopsisBody) {
// Match the height of the synopsis card to the cover card
const coverHeight = coverCard.offsetHeight;
synopsisCard.style.height = `${coverHeight}px`;
// Adjust the synopsis body to scroll within the matched height
const headerHeight = synopsisCard.querySelector(".card-header").offsetHeight;
synopsisBody.style.maxHeight = `${coverHeight - headerHeight}px`;
}
});
</script>
<script>
fetch('https://ipapi.co/json/')
.then(response => response.json())
.then(data => {
const country = data.country_code;
let amazonLink = "https://www.amazon.com/dp/B0FBS427VD";
switch (country) {
case "GB":
amazonLink = "https://www.amazon.co.uk/dp/B0FBS427VD";
break;
case "US":
amazonLink = "https://www.amazon.com/dp/B0FBS427VD";
break;
case "CA":
amazonLink = "https://www.amazon.ca/dp/B0FBS427VD";
break;
case "AU":
amazonLink = "https://www.amazon.com.au/dp/B0FBS427VD";
break;
}
document.getElementById("amazonLink").setAttribute("href", amazonLink);
});
</script>
}
@section Meta{
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "Book",
"name": "The Alpha Flame: Discovery",
"alternateName": "The Alpha Flame Book 1",
"author": {
"@@type": "Person",
"name": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com"
},
"publisher": {
"@@type": "Organization",
"name": "Catherine Lynwood"
},
"datePublished": "2025-08-21",
"description": "The Alpha Flame: Discovery is a powerful, character-driven novel set in 1983 Birmingham, following Maggie Grant and Beth—two young women separated by fate, reunited by truth, and bound by secrets. As past traumas resurface and danger closes in, their journey through survival, sisterhood, and redemption begins.",
"genre": "Women's Fiction, Mystery, Contemporary Historical",
"inLanguage": "en-GB",
"url": "https://www.catherinelynwood.com/the-alpha-flame/discovery",
"workExample": [
{
"@@type": "Book",
"bookFormat": "https://schema.org/Hardcover",
"isbn": "978-1-0682258-0-2",
"name": "The Alpha Flame: Discovery Hardback"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/Paperback",
"isbn": "978-1-0682258-1-9",
"name": "The Alpha Flame: Discovery Softback"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/Paperback",
"isbn": "978-1-0682258-2-6",
"name": "The Alpha Flame: Discovery Amazon Edition"
},
{
"@@type": "Book",
"bookFormat": "https://schema.org/EBook",
"isbn": "978-1-0682258-3-3",
"name": "The Alpha Flame: Discovery eBook"
}
]
}
</script>
}

View File

@ -0,0 +1,180 @@
@{
ViewData["Title"] = "Extras";
int? accessLevel = Context.Session.GetInt32("BookAccessLevel");
int? accessBook = Context.Session.GetInt32("BookAccessMax");
}
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item active" aria-current="page"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li>
<li class="breadcrumb-item active" aria-current="page">Extras</li>
</ol>
</nav>
</div>
</div>
<div class="container mt-5">
<h1 class="extras-header">Your Exclusive Extras</h1>
@if (accessLevel >= 1)
{
<div class="extras-grid mt-4">
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Epilogue</h5>
<p class="card-text">Immerse yourself in the Eplilogue to The Alpha Flame: Discovery. Join the team as they relax for a quite drink at the Barnt Green Inn</p>
<a asp-controller="Discovery" asp-action="Epilogue" class="btn btn-dark btn-sm">Read or Listen</a>
</div>
</div>
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Discovery Scrap Book</h5>
<p class="card-text">Take a look at my image scrapbook for The Alpha Flame: Discovery. View the images I used for inspiration when writing the various scenes within the book.</p>
<a asp-controller="Discovery" asp-action="ScrapBook" class="btn btn-dark btn-sm">View Scrapbook</a>
</div>
</div>
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Rubery Hill Photo Archive</h5>
<p class="card-text">Explore historical photos and floor plans of the real Rubery Hill Hospital, the eerie inspiration behind key scenes.</p>
<a href="/extras/rubery-hill-photos" class="btn btn-dark btn-sm">Explore</a>
</div>
</div>
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Scrapbook: Maggies Designs</h5>
<p class="card-text">Flip through Maggies sketches, fashion notes, and photos from her original designs including the infamous red skirt.</p>
<a asp-controller="Discovery" asp-action="MaggiesDesigns" class="btn btn-dark btn-sm">View Scrapbook</a>
</div>
</div>
</div>
}
else if (accessLevel >= 2)
{
<div class="extras-grid mt-4">
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Epilogue</h5>
<p class="card-text">Immerse yourself in the Eplilogue to The Alpha Flame: Discovery. Join the team as they relax for a quite drink at the Barnt Green Inn</p>
<a asp-controller="Discovery" asp-action="Epilogue" class="btn btn-dark btn-sm">Read or Listen</a>
</div>
</div>
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Discovery Scrap Book</h5>
<p class="card-text">Take a look at my image scrapbook for The Alpha Flame: Discovery. View the images I used for inspiration when writing the various scenes within the book.</p>
<a asp-controller="Discovery" asp-action="ScrapBook" class="btn btn-dark btn-sm">View Scrapbook</a>
</div>
</div>
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Rubery Hill Photo Archive</h5>
<p class="card-text">Explore historical photos and floor plans of the real Rubery Hill Hospital, the eerie inspiration behind key scenes.</p>
<a href="/extras/rubery-hill-photos" class="btn btn-dark btn-sm">Explore</a>
</div>
</div>
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Scrapbook: Maggies Designs</h5>
<p class="card-text">Flip through Maggies sketches, fashion notes, and photos from her original designs including the infamous red skirt.</p>
<a asp-controller="Discovery" asp-action="MaggiesDesigns" class="btn btn-dark btn-sm">View Scrapbook</a>
</div>
</div>
</div>
}
else if (accessLevel >= 3)
{
<div class="extras-grid mt-4">
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Epilogue</h5>
<p class="card-text">Immerse yourself in the Eplilogue to The Alpha Flame: Discovery. Join the team as they relax for a quite drink at the Barnt Green Inn</p>
<a asp-controller="Discovery" asp-action="Epilogue" class="btn btn-dark btn-sm">Read or Listen</a>
</div>
</div>
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Discovery Scrap Book</h5>
<p class="card-text">Take a look at my image scrapbook for The Alpha Flame: Discovery. View the images I used for inspiration when writing the various scenes within the book.</p>
<a asp-controller="Discovery" asp-action="ScrapBook" class="btn btn-dark btn-sm">View Scrapbook</a>
</div>
</div>
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Rubery Hill Photo Archive</h5>
<p class="card-text">Explore historical photos and floor plans of the real Rubery Hill Hospital, the eerie inspiration behind key scenes.</p>
<a href="/extras/rubery-hill-photos" class="btn btn-dark btn-sm">Explore</a>
</div>
</div>
<div class="card extra-card">
<div class="card-body">
<h5 class="card-title">Scrapbook: Maggies Designs</h5>
<p class="card-text">Flip through Maggies sketches, fashion notes, and photos from her original designs including the infamous red skirt.</p>
<a asp-controller="Discovery" asp-action="MaggiesDesigns" class="btn btn-dark btn-sm">View Scrapbook</a>
</div>
</div>
</div>
}
</div>
@section Meta{
<style>
.extras-header {
text-align: center;
margin-top: 3rem;
margin-bottom: 2rem;
}
.extra-card {
border: none;
border-radius: 1rem;
box-shadow: 0 0 15px rgba(0,0,0,0.1);
transition: transform 0.2s ease;
}
.extra-card:hover {
transform: translateY(-5px);
}
.card-title {
font-weight: bold;
font-size: 1.25rem;
}
.card-text {
font-size: 0.95rem;
}
.extras-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
.access-label {
font-size: 0.8rem;
font-style: italic;
color: #888;
}
</style>
}

View File

@ -1,37 +0,0 @@
@{
ViewData["Title"] = "The Alpha Flame | Front Cover";
}
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item"><a asp-controller="TheAlphaFlame" asp-action="Index">The Alpha Flame</a></li>
<li class="breadcrumb-item active" aria-current="page">Front Cover</li>
</ol>
</nav>
</div>
</div>
<div class="row">
<div class="col-12">
<section id="cover" class="mb-5">
<div class="card">
<responsive-image src="the-alpha-flame-10.png" class="card-img-top" alt="The Alpha Flame Cover" display-width-percentage="100"></responsive-image>
<div class="card-body">
<h2 class="card-title">Front Cover Draft</h2>
<p class="card-text">
I've had a few different versions of my front cover, and I'm a little undecided, however I'm now favouring the more dramatic version.
</p>
<p class="card-text">
The girl in the image is a representation of the main character, Maggie, and the flames are a metaphor for the fire that consumes her life, and also a more literal reference to her hair.
</p>
<p class="card-text">
There is also a hint towards one of the more dramatic scenes I'm proposing nearer to the end of my book. I don't want to give too much away, but even though Maggie looks kind of delicate and dainty, she's a force to be reckoned with, and woe betide anyone who crosses her on her quest.
</p>
</div>
</div>
</section>
</div>
</div>

View File

@ -12,114 +12,124 @@
</nav> </nav>
</div> </div>
</div> </div>
<div class="row">
<div class="container py-5">
<div class="text-center mb-5">
<h1 class="display-5 fw-bold">The Alpha Flame Trilogy</h1>
<p class="lead">
A powerful series of love, trauma, discovery and transformation.
Follow Maggie and Beth as they navigate a world full of secrets, shadows, and the flicker of hope that refuses to die.
Across three unforgettable books, the Alpha Flame burns ever brighter.
</p>
</div>
<!-- Book 1: Full-width Featured -->
<div class="row mb-5">
<div class="col-12"> <div class="col-12">
<div class="card h-100 shadow-lg border-3 border-warning">
<div class="row g-0">
<!-- Chapter Previews --> <div class="col-md-3">
<section id="chapters"> <a href="/the-alpha-flame/discovery">
<h2>Book Previews</h2> <responsive-image src="the-alpha-flame-11.png" class="img-fluid rounded-start-3" alt="The Alpha Flame: Discovery" display-width-percentage="100"></responsive-image>
<div class="row mt-3">
<!-- Chapter 1 Preview -->
<div class="col-md-4 mb-4">
<div class="card h-100 character-card">
<a asp-action="FrontCover">
<responsive-image src="the-alpha-flame-10.png" class="card-img-top" alt="The Alpha Flame Cover" display-width-percentage="50"></responsive-image>
</a>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">The Front Cover</h3>
<p class="card-text">In the quieter moments when I'm not writing I've been spending some time working on the cover of my book. It's definitely early days at the moment, but you can take a look at a draft version of the front cover if you wish.'</p>
<div class="text-end"><a asp-action="FrontCover" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
<!-- Chapter 1 Preview -->
<div class="col-md-4 mb-4">
<div class="card h-100 character-card">
<a asp-action="Chapter1">
<responsive-image src="beth-13.png" class="card-img-top" alt="Beth Fletcher in her flat" display-width-percentage="50"></responsive-image>
</a>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">Chapter 1: Drowning in Silence - Beth</h3>
<p class="card-text">Beth returns home to find her mother lifeless in the bath, an empty bottle beside her. Overwhelmed by grief and disbelief, she wrestles with feelings of abandonment and anger as her world shatters around her. Left alone at just sixteen, Beth faces the bleak realities of life without her mother, including navigating the cold and impersonal system of social services. When her estranged aunt briefly steps in before leaving her completely alone, Beth is forced to make a desperate decision—to run away and forge her own path, no matter the cost.</p>
<div class="text-end"><a asp-action="Chapter1" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
<!-- Chapter 2 Preview -->
<div class="col-md-4 mb-4">
<div class="card h-100 character-card">
<a asp-action="Chapter2">
<responsive-image src="maggie-grant-44.png" class="card-img-top" alt="Maggie Grant, The Alpha Flame" display-width-percentage="50"></responsive-image>
</a>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">Chapter 2: The Last Lesson - Maggie</h3>
<p class="card-text">On Christmas Eve, Maggie nervously heads out for her driving test, determined to succeed. Dressed to impress and brimming with playful confidence, she charms her instructor Colin and even turns heads at the test center. However, an unexpected incident involving a child running into the road tests her composure and skill. Maggies quick thinking earns her a perfect pass, and she celebrates with her family and best friend, Rosie. Driving her newly restored Triumph TR6 for the first time, Maggie revels in her freedom but cant shake the haunting image of a lonely girl she spots under a flyover, sparking a lingering sense of unease.</p>
<div class="text-end"><a asp-action="Chapter2" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
<div class="col-12 mb-4 px-4">
<div class="row rounded-5 border border-3 border-dark overflow-hidden">
<div class="col-md-4 p-0 responsive-border border-3 border-dark">
<a asp-action="Characters">
<responsive-image src="maggie-grant-47.png" class="fit-image" alt="Maggie Grant, The Alpha Flame" display-width-percentage="50"></responsive-image>
</a> </a>
</div> </div>
<div class="col-md-8 bg-light text-dark p-3"> <div class="col-md-9">
<h3 class="card-title">Meet the Characters</h3> <div class="card-body">
<div class="card-text"> <h3 class="card-title">The Alpha Flame: <span class="fw-light">Discovery</span></h3>
<p>Dive into the vibrant world of The Alpha Flame and discover the unforgettable cast of characters that bring this story to life.</p> <p class="fst-italic">Some girls survive. Others set the world on fire.</p>
<p>
<p>Get to know Maggie, the fiery and magnetic heart of the tale, and Beth, whose troubled past contrasts with her unyielding strength. Meet Rosie, Maggie's best friend, who brings warmth and humor to every scene, and Rebecca, a steady presence with a hidden depth.</p> Maggie didnt go looking for trouble. But when she found Beth—bruised, broken, and terrified—she couldnt walk away.
</p>
<p>Explore the mind of Rob, the gadget-obsessed photographer whose quiet determination matches his deep connection to Maggie. Then theres Zoe, the sharp-witted ex-policewoman whos full of surprises.</p> <p>
What begins as a rescue becomes something far more dangerous. Drawn into Beths world, Maggie is forced to confront a hidden undercurrent of control, abuse, and corruption that runs deeper than she ever imagined. A seedy underworld of silence and survival where nothing is as it seems, and walking away is no longer an option.
<p>Not everyone is a friend, though—Sophie brings tension and drama with her prickly demeanor, and Rick, the dark and dangerous antagonist, keeps the stakes high and the tension palpable.</p> </p>
<p>
<p>Find out what makes them tick, what drives their actions, and what secrets theyre hiding. Who will you root for, and who will you love to hate? Discover it all in The Alpha Flame.</p> As truths unravel and pasts collide, Maggie must decide who she is, who she trusts, and how far she's willing to go for someone she barely knows… yet feels inexplicably bound to.
</div> </p>
<div class="text-end"><a asp-action="Characters" class="btn btn-dark">Read More</a></div> <p class="fw-semibold">
</div> <em>The Alpha Flame: Discovery</em> is a gritty, emotionally charged thriller about trauma, loyalty, and fire—forged in pain, and burning with truth.
</div> </p>
</div> <div class="mt-auto text-end">
</div> <a href="/the-alpha-flame/discovery" class="btn btn-dark">Read More</a>
</section>
</div> </div>
</div> </div>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-12">
<div class="card h-100 shadow-sm border-start border-3 border-warning position-relative">
<span class="badge bg-warning text-dark position-absolute top-0 start-0 m-2">Coming Spring 2026</span>
<div class="row g-0">
<div class="col-md-2">
<responsive-image src="the-alpha-flame-10.png" class="img-fluid rounded-start placeholder-blur" alt="The Alpha Flame: Reckoning" display-width-percentage="100"></responsive-image>
</div>
<div class="col-md-10">
<div class="card-body">
<h5 class="card-title">The Alpha Flame: <span class="fw-light">Reckoning</span></h5>
<p class="card-text">
As truths begin to unravel, *The Alpha Flame: Reckoning* plunges deeper into the aftermath of choices made and sins buried.
The cost of survival is rising, and the ghosts of the past demand payment in full.
</p>
<p class="card-text">
With loyalties tested and new threats circling, the flame that once brought light now threatens to consume. Darker, more daring, and laced with tension, the second book refuses to flinch from the consequences of truth.
</p>
<div class="mt-auto text-end">
<a href="#" class="btn btn-dark disabled">Coming 2026</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-12">
<div class="card h-100 shadow-sm border-start border-3 border-warning position-relative">
<span class="badge bg-warning text-dark position-absolute top-0 start-0 m-2">Coming Autumn 2026</span>
<div class="row g-0">
<div class="col-md-2">
<responsive-image src="the-alpha-flame-10.png" class="img-fluid rounded-start placeholder-blur" alt="The Alpha Flame: Redemption" display-width-percentage="100"></responsive-image>
</div>
<div class="col-md-10">
<div class="card-body">
<h5 class="card-title">The Alpha Flame: <span class="fw-light">Redemption</span></h5>
<p class="card-text">
Every fire must either burn out or forge something stronger. *The Alpha Flame: Redemption* is a story of confronting whats been lost, whats been taken, and what might still be saved.
</p>
<p class="card-text">
As the final pieces fall into place, the women at the heart of the flame must decide if healing is possible—or if some wounds are meant to stay open. Fierce, emotional, and defiantly human, this final chapter brings the trilogy to a powerful close.
</p>
<div class="mt-auto text-end">
<a href="#" class="btn btn-dark disabled">Coming 2026</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@section Meta { @section Meta {
<meta name="description" content="Explore The Alpha Flame, a novel by Catherine Lynwood. Dive into the story of passion, love, and power with strong characters and compelling themes."> <style>
.placeholder-blur {
<meta name="keywords" content="The Alpha Flame, Catherine Lynwood, novel, book cover, story of passion, love, power, strong characters, compelling themes"> filter: blur(4px);
opacity: 0.7;
<meta name="author" content="Catherine Lynwood"> transition: filter 0.3s ease, opacity 0.3s ease;
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "WebPage",
"name": "The Alpha Flame - Cover Page",
"description": "Explore The Alpha Flame, a novel by Catherine Lynwood. Dive into the story of passion, love, and power with strong characters and compelling themes.",
"url": "https://www.catherinelynwood.com/the-alpha-flame",
"author": {
"@@type": "Person",
"name": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com"
},
"about": {
"@@type": "CreativeWork",
"name": "The Alpha Flame",
"description": "A captivating novel about passion, love, and power."
},
"isPartOf": {
"@@type": "WebSite",
"name": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com"
} }
}
</script>
.placeholder-blur:hover {
filter: blur(2px);
opacity: 0.9;
}
</style>
} }

View File

@ -0,0 +1,167 @@
@{
ViewData["Title"] = "The Alpha Flame";
}
<div class="row">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a asp-controller="Home" asp-action="Index">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">The Alpha Flame</li>
</ol>
</nav>
</div>
</div>
<div class="row">
<div class="col-12">
<section>
<div class="row">
<div class="col-12">
<div class="card character-card">
<div class="card-header">
<h1>The Alpha Flame</h1>
</div>
<div class="card-img bg-dark">
<div class="ratio ratio-16x9">
<video controls="controls" poster="/images/Synopsis.png">
<source src="~/videos/Synopsis.mp4" type="video/mp4"/>
</video>
</div>
</div>
<div class="card-body border-top border-3 border-dark bg-light">
<h3 class="card-title">Synopsis</h3>
<p class="card-text">The Alpha Flame is an unflinching and deeply emotional story of resilience, love, and survival, set against the vibrant yet tumultuous backdrop of 1983. Through the intersecting lives of two heroines, it delves into the extremes of human suffering and the boundless power of the human spirit to endure, adapt, and rise.</p>
<p class="card-text">For Beth, the world is a cold and unforgiving place. Devastation strikes in a single moment, leaving her isolated, shattered, and vulnerable. Alone in the bleak shadows of a city that offers neither refuge nor redemption, she is forced to navigate a relentless cycle of desperation and despair. Every step of her journey tests the limits of her endurance, pushing her into harrowing situations where survival feels like a hollow victory. Beths existence is marked by loss, betrayal, and an almost suffocating loneliness that threatens to consume her entirely. Yet, even in the darkest corners of her ordeal, a fragile ember of defiance smoulders within her—a quiet, stubborn refusal to let the world destroy her completely.</p>
<p class="card-text">Maggie, by contrast, is a force of nature—a woman who thrives on her unshakable drive and an unrelenting belief in her own power. Behind her fiery red hair and disarming charm lies a storm of determination and ferocity. Maggie doesnt just live; she races through life, fuelled by a need for speed and the thrill of freedom. Her Triumph TR6 isnt just a car; its an extension of her spirit—sleek, powerful, and unapologetically bold. On the open road, with the engine roaring and the world blurring past her, she feels invincible. But Maggies intensity doesnt stop at the wheel. Her relationships burn just as brightly. As a lover, she is dominant, passionate, and unafraid to embrace her darker desires. While fiercely loving and loyal, Maggie is also formidable; crossing her isnt a mistake anyone makes twice.</p>
<p class="card-text">When fate brings Beth and Maggie together, their connection is explosive—a union of two polar opposites that burns with both tenderness and raw power. For Beth, Maggie represents a lifeline, a reminder that love and trust still exist, even in a world that has betrayed her at every turn. For Maggie, Beth awakens a fierce protectiveness and vulnerability shes rarely allowed herself to feel. Together, they ignite a flame that challenges them to confront their own fears, desires, and limitations.</p>
<p class="card-text">Set against the kaleidoscope of 1983—where synthesised anthems provide a pulsing soundtrack and the streets are alive with the bold styles and rebellious energy of the decade—their story unfolds in a city teeming with danger and intrigue. From high-speed chases along winding roads to dimly lit clubs and desolate alleyways, the heroines journey is a visceral exploration of survival and freedom. The neon haze of the era contrasts sharply with the stark realities they face, painting a vivid picture of a world where strength and vulnerability coexist.</p>
<p class="card-text">As secrets surface and danger tightens its grip, Beth and Maggie must confront not only the challenges around them but the truths within themselves. Their bond is tested by betrayal, desire, and the shadows of their pasts, but through it all, their flame burns brighter, illuminating their courage and the unbreakable spirit of two heroines determined to rewrite their fates.</p>
<p class="card-text">At its heart, The Alpha Flame is a story of survival, passion, and empowerment. It explores the devastating lows and triumphant highs of life with unflinching honesty, capturing the raw power of human connection against the gritty, vibrant backdrop of an unforgettable era. With its blend of drama, intensity, and unapologetic emotion, this is a story that will leave its mark long after the final frame.</p>
</div>
</div>
</div>
</div>
</section>
<!-- Chapter Previews -->
<section id="chapters">
<h2>Book Previews</h2>
<div class="row mt-3">
<!-- Chapter 1 Preview -->
<div class="col-md-4 mb-4">
<div class="card h-100 character-card">
<a asp-action="FrontCover">
<responsive-image src="the-alpha-flame-10.png" class="card-img-top" alt="The Alpha Flame Cover" display-width-percentage="50"></responsive-image>
</a>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">The Front Cover</h3>
<p class="card-text">In the quieter moments when I'm not writing I've been spending some time working on the cover of my book. It's definitely early days at the moment, but you can take a look at a draft version of the front cover if you wish.'</p>
<div class="text-end"><a asp-action="FrontCover" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
<!-- Chapter 1 Preview -->
<div class="col-md-4 mb-4">
<div class="card h-100 character-card">
<a asp-action="Chapter1">
<responsive-image src="beth-13.png" class="card-img-top" alt="Beth Fletcher in her flat" display-width-percentage="50"></responsive-image>
</a>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">Chapter 1: Drowning in Silence - Beth</h3>
<p class="card-text">Beth returns home to find her mother lifeless in the bath, an empty bottle beside her. Overwhelmed by grief and disbelief, she wrestles with feelings of abandonment and anger as her world shatters around her. Left alone at just sixteen, Beth faces the bleak realities of life without her mother, including navigating the cold and impersonal system of social services. When her estranged aunt briefly steps in before leaving her completely alone, Beth is forced to make a desperate decision—to run away and forge her own path, no matter the cost.</p>
<div class="text-end"><a asp-action="Chapter1" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
<!-- Chapter 2 Preview -->
<div class="col-md-4 mb-4">
<div class="card h-100 character-card">
<a asp-action="Chapter2">
<responsive-image src="maggie-grant-44.png" class="card-img-top" alt="Maggie Grant, The Alpha Flame" display-width-percentage="50"></responsive-image>
</a>
<div class="card-body border-top border-3 border-dark">
<h3 class="card-title">Chapter 2: The Last Lesson - Maggie</h3>
<p class="card-text">On Christmas Eve, Maggie nervously heads out for her driving test, determined to succeed. Dressed to impress and brimming with playful confidence, she charms her instructor Colin and even turns heads at the test center. However, an unexpected incident involving a child running into the road tests her composure and skill. Maggies quick thinking earns her a perfect pass, and she celebrates with her family and best friend, Rosie. Driving her newly restored Triumph TR6 for the first time, Maggie revels in her freedom but cant shake the haunting image of a lonely girl she spots under a flyover, sparking a lingering sense of unease.</p>
<div class="text-end"><a asp-action="Chapter2" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
<div class="col-12 mb-4 px-4">
<div class="row rounded-5 border border-3 border-dark overflow-hidden">
<div class="col-md-4 p-0 responsive-border border-3 border-dark">
<a asp-action="Characters">
<responsive-image src="maggie-grant-47.png" class="fit-image" alt="Maggie Grant, The Alpha Flame" display-width-percentage="50"></responsive-image>
</a>
</div>
<div class="col-md-8 bg-light text-dark p-3">
<h3 class="card-title">Meet the Characters</h3>
<div class="card-text">
<p>Dive into the vibrant world of The Alpha Flame and discover the unforgettable cast of characters that bring this story to life.</p>
<p>Get to know Maggie, the fiery and magnetic heart of the tale, and Beth, whose troubled past contrasts with her unyielding strength. Meet Rosie, Maggie's best friend, who brings warmth and humor to every scene, and Rebecca, a steady presence with a hidden depth.</p>
<p>Explore the mind of Rob, the gadget-obsessed photographer whose quiet determination matches his deep connection to Maggie. Then theres Zoe, the sharp-witted ex-policewoman whos full of surprises.</p>
<p>Not everyone is a friend, though—Sophie brings tension and drama with her prickly demeanor, and Rick, the dark and dangerous antagonist, keeps the stakes high and the tension palpable.</p>
<p>Find out what makes them tick, what drives their actions, and what secrets theyre hiding. Who will you root for, and who will you love to hate? Discover it all in The Alpha Flame.</p>
</div>
<div class="text-end"><a asp-action="Characters" class="btn btn-dark">Read More</a></div>
</div>
</div>
</div>
</div>
</section>
</div>
</div>
@section Meta {
<meta name="description" content="Explore The Alpha Flame, a novel by Catherine Lynwood. Dive into the story of passion, love, and power with strong characters and compelling themes.">
<meta name="keywords" content="The Alpha Flame, Catherine Lynwood, novel, book cover, story of passion, love, power, strong characters, compelling themes">
<meta name="author" content="Catherine Lynwood">
<meta name="twitter:card" content="player">
<meta name="twitter:site" content="@@CathLynwood">
<meta name="twitter:title" content="The Alpha Flame">
<meta name="twitter:description" content="Experience the gripping trailer of The Alpha Flame by Catherine Lynwood, a tale of love, loss, and self-discovery.">
<meta name="twitter:image" content="https://www.catherinelynwood.com/images/Synopsis.png">
<meta name="twitter:player" content="https://www.catherinelynwood.com/videos/Synopsis.mp4">
<meta name="twitter:player:width" content="640">
<meta name="twitter:player:height" content="360">
<meta name="twitter:player:stream" content="https://www.catherinelynwood.com/videos/Synopsis.mp4">
<meta name="twitter:player:stream:content_type" content="video/mp4">
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "WebPage",
"name": "The Alpha Flame - Cover Page",
"description": "Explore The Alpha Flame, a novel by Catherine Lynwood. Dive into the story of passion, love, and power with strong characters and compelling themes.",
"url": "https://www.catherinelynwood.com/the-alpha-flame",
"author": {
"@@type": "Person",
"name": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com"
},
"about": {
"@@type": "CreativeWork",
"name": "The Alpha Flame",
"description": "A captivating novel about passion, love, and power."
},
"isPartOf": {
"@@type": "WebSite",
"name": "Catherine Lynwood",
"url": "https://www.catherinelynwood.com"
}
}
</script>
}

View File

@ -24,6 +24,15 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<figure class="figure w-sm-50 p-3">
<div class="figure-img ratio ratio-16x9 rounded-5 border border-dark border-3 bg-dark">
<video controls="controls" autoplay="autoplay" poster="/images/Synopsis-Maggie.png" class="rounded-5">
<source src="~/videos/Synopsis-Maggie.mp4" type="video/mp4" />
</video>
</div>
<figcaption class="figure-caption">Watch Maggie tell you about her story.</figcaption>
</figure>
<div class="float-sm-end w-sm-50 p-3"> <div class="float-sm-end w-sm-50 p-3">
<div id="carouselControls" class="carousel slide" data-bs-ride="carousel"> <div id="carouselControls" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner"> <div class="carousel-inner">
@ -59,7 +68,10 @@
</button> </button>
</div> </div>
</div> </div>
<h2 class="mb-3">Overview</h2>
<p>Maggie Grant is the fiery and complex heroine of <em>The Alpha Flame:</em>. With her striking red hair, sharp wit, and magnetic personality, she is a force to be reckoned with. Maggies journey is one of self-discovery, resilience, and dominance, as she navigates a world full of challenges, betrayal, and passion.</p> <p>Maggie Grant is the fiery and complex heroine of <em>The Alpha Flame:</em>. With her striking red hair, sharp wit, and magnetic personality, she is a force to be reckoned with. Maggies journey is one of self-discovery, resilience, and dominance, as she navigates a world full of challenges, betrayal, and passion.</p>
<p>Born and raised in a modest town, Maggies life takes unexpected turns that shape her into the strong woman she becomes. Her natural charisma and keen intelligence make her a leader in any room, but its her unwavering determination that sets her apart. Maggie doesnt just survive—she thrives, finding ways to take control of situations that would leave others defeated.</p> <p>Born and raised in a modest town, Maggies life takes unexpected turns that shape her into the strong woman she becomes. Her natural charisma and keen intelligence make her a leader in any room, but its her unwavering determination that sets her apart. Maggie doesnt just survive—she thrives, finding ways to take control of situations that would leave others defeated.</p>
@ -162,6 +174,18 @@
<meta name="author" content="Catherine Lynwood"> <meta name="author" content="Catherine Lynwood">
<meta name="twitter:card" content="player">
<meta name="twitter:site" content="@@CathLynwood">
<meta name="twitter:title" content="Maggie Grant | The Alpha Flame">
<meta name="twitter:description" content="Dive into the captivating world of The Alpha Flame and meet Maggie Grant, a character full of depth and intrigue.">
<meta name="twitter:image" content="https://www.catherinelynwood.com/images/Synopsis-Maggie.png">
<meta name="twitter:player" content="https://www.catherinelynwood.com/videos/Synopsis-Maggie.mp4">
<meta name="twitter:player:width" content="640">
<meta name="twitter:player:height" content="360">
<meta name="twitter:player:stream" content="https://www.catherinelynwood.com/videos/Synopsis-Maggie.mp4">
<meta name="twitter:player:stream:content_type" content="video/mp4">
<script type="application/ld+json"> <script type="application/ld+json">
{ {
"@@context": "https://schema.org", "@@context": "https://schema.org",

View File

@ -0,0 +1,5 @@
@*
For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
}

View File

@ -0,0 +1,5 @@
@*
For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
}

View File

@ -28,5 +28,11 @@
"inputFiles": [ "inputFiles": [
"wwwroot/css/site.css" "wwwroot/css/site.css"
] ]
},
{
"outputFileName": "wwwroot/css/bootstrap.min.css",
"inputFiles": [
"wwwroot/css/bootstrap.css"
]
} }
] ]

Binary file not shown.

View File

@ -196,3 +196,6 @@ section {
background-color: #010101; background-color: #010101;
} }
#synopsis-body {
overflow-y: auto;
}

View File

@ -1 +1 @@
html{font-size:14px}@media(min-width:768px){html{font-size:16px}}html{position:relative}.content{min-height:95vh}.fixed-background{position:fixed;top:0;left:0;width:100vw;height:100vh;background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-1920.webp');background-size:cover;background-repeat:no-repeat;background-position:top;z-index:-1}@media(max-width:575.98px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-400.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}@media(min-width:576px) and (max-width:767.98px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-768.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}@media(min-width:768px) and (max-width:991.98px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-992.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}@media(min-width:992px) and (max-width:1199.98px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-1200.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}@media(min-width:1200px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-1920.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}.content{position:relative;z-index:1}section{padding-bottom:10px}.w-sm-50{width:100%}@media(min-width:576px){.w-sm-50{width:50%}}.w-md-50{width:100%}@media(min-width:768px){.w-md-50{width:50%}}.excerpt-section{background-color:#f8f9fa}.scene-image{max-width:100%;height:auto;border-radius:10px}.audio-player{margin:1rem 0}.chapter-text{font-family:'Georgia',serif;font-size:1.1rem;line-height:1.6;color:#333}.chapter-title{font-size:1.5rem;font-weight:bold;color:#555;margin-bottom:1rem}.responsive-border{border-right:3px solid #000}@media(max-width:575.98px){.responsive-border{border-right:0;border-bottom:3px solid #000}}.fit-image{width:100%;height:100%;object-fit:cover;object-position:center;display:block}.share-button{padding:8px 12px;margin-left:10px;margin-right:10px;color:#fff;text-decoration:none;border-radius:4px;font-size:14px}.share-button.facebook{background-color:#3b5998}.share-button.twitter{background-color:#1da1f2}.share-button.linkedin{background-color:#0077b5}.share-button.pinterest{background-color:#bd081c}.share-button.instagram{background-color:#e4405f}.share-button.tiktok{background-color:#010101} html{font-size:14px}@media(min-width:768px){html{font-size:16px}}html{position:relative}.content{min-height:95vh}.fixed-background{position:fixed;top:0;left:0;width:100vw;height:100vh;background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-1920.webp');background-size:cover;background-repeat:no-repeat;background-position:top;z-index:-1}@media(max-width:575.98px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-400.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}@media(min-width:576px) and (max-width:767.98px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-768.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}@media(min-width:768px) and (max-width:991.98px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-992.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}@media(min-width:992px) and (max-width:1199.98px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-1200.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}@media(min-width:1200px){.fixed-background{background:linear-gradient(rgba(23,200,235,.5),rgba(23,200,235,.5)),url('/images/webp/maggie-5-1920.webp');background-size:cover;background-repeat:no-repeat;background-position:top}}.content{position:relative;z-index:1}section{padding-bottom:10px}.w-sm-50{width:100%}@media(min-width:576px){.w-sm-50{width:50%}}.w-md-50{width:100%}@media(min-width:768px){.w-md-50{width:50%}}.excerpt-section{background-color:#f8f9fa}.scene-image{max-width:100%;height:auto;border-radius:10px}.audio-player{margin:1rem 0}.chapter-text{font-family:'Georgia',serif;font-size:1.1rem;line-height:1.6;color:#333}.chapter-title{font-size:1.5rem;font-weight:bold;color:#555;margin-bottom:1rem}.responsive-border{border-right:3px solid #000}@media(max-width:575.98px){.responsive-border{border-right:0;border-bottom:3px solid #000}}.fit-image{width:100%;height:100%;object-fit:cover;object-position:center;display:block}.share-button{padding:8px 12px;margin-left:10px;margin-right:10px;color:#fff;text-decoration:none;border-radius:4px;font-size:14px}.share-button.facebook{background-color:#3b5998}.share-button.twitter{background-color:#1da1f2}.share-button.linkedin{background-color:#0077b5}.share-button.pinterest{background-color:#bd081c}.share-button.instagram{background-color:#e4405f}.share-button.tiktok{background-color:#010101}#synopsis-body{overflow-y:auto}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Some files were not shown because too many files have changed in this diff Show More